From b01047730e77127c23a36591643eeb8bb0487d68 Mon Sep 17 00:00:00 2001 From: Pascal Brand Date: Thu, 12 Jun 2014 15:56:20 +0200 Subject: [PATCH] Open-source the TEE Core Signed-off-by: Pascal Brand --- .gitignore | 5 + LICENSE | 27 + Makefile | 41 + Notice.md | 35 + core/arch/arm32/include/arm32.h | 161 + core/arch/arm32/include/arm32_macros.S | 54 + core/arch/arm32/include/kernel/arch_debug.h | 33 + core/arch/arm32/include/kernel/asc.h | 35 + core/arch/arm32/include/kernel/kta_types.h | 86 + core/arch/arm32/include/kernel/misc.h | 36 + .../arm32/include/kernel/tee_l2cc_mutex.h | 28 + core/arch/arm32/include/kernel/tee_misc.h | 51 + core/arch/arm32/include/kernel/thread.h | 220 ++ core/arch/arm32/include/kernel/thread_defs.h | 38 + core/arch/arm32/include/kernel/tz_proc.h | 53 + core/arch/arm32/include/kernel/tz_proc_def.h | 167 + core/arch/arm32/include/kernel/tz_ssvce.h | 58 + core/arch/arm32/include/kernel/tz_ssvce_def.h | 69 + core/arch/arm32/include/mm/core_memprot.h | 93 + core/arch/arm32/include/mm/core_mmu.h | 145 + core/arch/arm32/include/mm/tee_mm_def.h | 143 + core/arch/arm32/include/mm/tee_mmu_defs.h | 96 + .../arch/arm32/include/mm/tee_pager_defines.h | 43 + core/arch/arm32/include/mm/tee_pager_unpg.h | 112 + core/arch/arm32/include/sm/sm.h | 95 + core/arch/arm32/include/sm/sm_defs.h | 41 + core/arch/arm32/include/sm/tee_mon.h | 44 + core/arch/arm32/include/sm/teesmc.h | 716 +++++ core/arch/arm32/include/sm/teesmc_st.h | 161 + core/arch/arm32/include/tee/entry.h | 49 + core/arch/arm32/kernel/chip_services.c | 44 + core/arch/arm32/kernel/misc.S | 39 + core/arch/arm32/kernel/sub.mk | 27 + core/arch/arm32/kernel/tee_core_trace.c | 215 ++ core/arch/arm32/kernel/tee_l2cc_mutex.c | 141 + core/arch/arm32/kernel/tee_misc.c | 94 + core/arch/arm32/kernel/tee_sleep_services.c | 72 + core/arch/arm32/kernel/tee_ta_manager.c | 1700 +++++++++++ core/arch/arm32/kernel/tee_time.c | 198 ++ core/arch/arm32/kernel/tee_time_unpg.c | 40 + core/arch/arm32/kernel/thread.c | 447 +++ core/arch/arm32/kernel/thread_asm.S | 397 +++ core/arch/arm32/kernel/thread_private.h | 158 + core/arch/arm32/kernel/tz_proc.S | 204 ++ core/arch/arm32/kernel/tz_ssvce.S | 846 +++++ core/arch/arm32/mm/core_mmu.c | 622 ++++ core/arch/arm32/mm/kta_table_unpg_asm.S | 124 + core/arch/arm32/mm/sub.mk | 20 + core/arch/arm32/mm/tee_mm.c | 259 ++ core/arch/arm32/mm/tee_mm_unpg.c | 63 + core/arch/arm32/mm/tee_mmu.c | 897 ++++++ core/arch/arm32/mm/tee_mmu_unpg.c | 49 + core/arch/arm32/mm/tee_mmu_unpg_asm.S | 113 + core/arch/arm32/mm/tee_pager.c | 134 + core/arch/arm32/mm/tee_pager_unpg.c | 386 +++ core/arch/arm32/mm/tee_pager_unpg_asm.S | 104 + core/arch/arm32/plat-orly2/.gitignore | 1 + core/arch/arm32/plat-orly2/asc.S | 181 ++ core/arch/arm32/plat-orly2/conf.mk | 69 + core/arch/arm32/plat-orly2/core_bootcfg.c | 307 ++ core/arch/arm32/plat-orly2/core_chip.c | 123 + core/arch/arm32/plat-orly2/link.mk | 41 + core/arch/arm32/plat-orly2/main.c | 264 ++ core/arch/arm32/plat-orly2/rng_support.c | 239 ++ core/arch/arm32/plat-orly2/sub.mk | 17 + core/arch/arm32/plat-orly2/system_config.in | 40 + core/arch/arm32/plat-orly2/tee_common_otp.c | 64 + core/arch/arm32/plat-orly2/tz-template.lds | 62 + core/arch/arm32/plat-orly2/tz_a9init.S | 425 +++ core/arch/arm32/plat-orly2/tz_sinit.S | 294 ++ core/arch/arm32/sm/sm.c | 46 + core/arch/arm32/sm/sm_asm.S | 215 ++ core/arch/arm32/sm/sub.mk | 5 + core/arch/arm32/sm/tee_mon.c | 87 + core/arch/arm32/sta/core_dirty_tests.c | 246 ++ core/arch/arm32/sta/core_dirty_tests.h | 37 + core/arch/arm32/sta/sta_helloworld.c | 251 ++ core/arch/arm32/sta/sub.mk | 6 + core/arch/arm32/tee/entry.c | 448 +++ core/arch/arm32/tee/sub.mk | 2 + core/arch/arm32/tee/tee_svc_asm.S | 257 ++ core/core.mk | 51 + core/default_signing.properties | 11 + core/drivers/gic.c | 213 ++ core/drivers/sub.mk | 2 + core/drivers/uart.c | 136 + core/include/asm.S | 56 + core/include/core_serviceid.h | 73 + core/include/drivers/gic.h | 44 + core/include/drivers/uart.h | 43 + core/include/io.h | 60 + core/include/kernel/chip_services.h | 45 + core/include/kernel/kernel.h | 38 + core/include/kernel/kta_mem.h | 78 + core/include/kernel/panic.h | 36 + core/include/kernel/tee_common.h | 74 + core/include/kernel/tee_common_otp.h | 45 + core/include/kernel/tee_common_unpg.h | 162 + core/include/kernel/tee_compat.h | 53 + core/include/kernel/tee_core_trace.h | 171 ++ core/include/kernel/tee_customer_part.h | 41 + core/include/kernel/tee_dispatch.h | 133 + core/include/kernel/tee_kta_trace.h | 163 + core/include/kernel/tee_misc_unpg.h | 48 + core/include/kernel/tee_rpc.h | 40 + core/include/kernel/tee_rpc_types.h | 38 + core/include/kernel/tee_sleep_services.h | 38 + core/include/kernel/tee_ta.h | 77 + core/include/kernel/tee_ta_manager.h | 121 + core/include/kernel/tee_ta_manager_unpg.h | 147 + core/include/kernel/tee_ta_static.h | 45 + core/include/kernel/tee_time.h | 44 + core/include/kernel/tee_time_unpg.h | 37 + core/include/mm/tee_mm.h | 87 + core/include/mm/tee_mm_unpg.h | 90 + core/include/mm/tee_mmu.h | 182 ++ core/include/mm/tee_mmu_io.h | 39 + core/include/mm/tee_mmu_types.h | 40 + core/include/mm/tee_mmu_unpg.h | 71 + core/include/rng_support.h | 34 + core/include/tee/tee_acipher.h | 78 + core/include/tee/tee_authenc.h | 63 + core/include/tee/tee_cipher.h | 60 + core/include/tee/tee_fs.h | 75 + core/include/tee/tee_fs_defs.h | 61 + core/include/tee/tee_hash.h | 59 + core/include/tee/tee_mac.h | 53 + core/include/tee/tee_obj.h | 59 + core/include/tee/tee_pobj.h | 54 + core/include/tee/tee_rpmb.h | 72 + core/include/tee/tee_rpmb_fs.h | 74 + core/include/tee/tee_svc.h | 101 + core/include/tee/tee_svc_cryp.h | 102 + core/include/tee/tee_svc_storage.h | 82 + core/kernel/assert.c | 41 + core/kernel/panic.c | 36 + core/kernel/sub.mk | 7 + core/kernel/tee_compat.c | 101 + core/kernel/tee_dispatch.c | 203 ++ core/kernel/tee_kta_trace.c | 90 + core/kernel/tee_ta_manager_unpg.c | 210 ++ .../lib/libtomcrypt/include/tee_ltc_wrapper.h | 42 + core/lib/libtomcrypt/include/tomcrypt.h | 114 + .../lib/libtomcrypt/include/tomcrypt_argchk.h | 65 + core/lib/libtomcrypt/include/tomcrypt_cfg.h | 168 + .../lib/libtomcrypt/include/tomcrypt_cipher.h | 584 ++++ .../lib/libtomcrypt/include/tomcrypt_custom.h | 401 +++ core/lib/libtomcrypt/include/tomcrypt_hash.h | 406 +++ core/lib/libtomcrypt/include/tomcrypt_mac.h | 411 +++ .../lib/libtomcrypt/include/tomcrypt_macros.h | 456 +++ core/lib/libtomcrypt/include/tomcrypt_math.h | 536 ++++ core/lib/libtomcrypt/include/tomcrypt_misc.h | 50 + core/lib/libtomcrypt/include/tomcrypt_mpa.h | 38 + core/lib/libtomcrypt/include/tomcrypt_pk.h | 603 ++++ core/lib/libtomcrypt/include/tomcrypt_pkcs.h | 116 + core/lib/libtomcrypt/include/tomcrypt_prng.h | 226 ++ core/lib/libtomcrypt/src/ciphers/aes.c | 787 +++++ core/lib/libtomcrypt/src/ciphers/aes_tab.c | 1057 +++++++ core/lib/libtomcrypt/src/ciphers/des.c | 1929 ++++++++++++ core/lib/libtomcrypt/src/ciphers/sub.mk | 5 + .../libtomcrypt/src/encauth/ccm/ccm_memory.c | 378 +++ .../libtomcrypt/src/encauth/ccm/ccm_test.c | 207 ++ core/lib/libtomcrypt/src/encauth/ccm/sub.mk | 2 + .../src/encauth/eax/eax_addheader.c | 65 + .../libtomcrypt/src/encauth/eax/eax_decrypt.c | 77 + .../encauth/eax/eax_decrypt_verify_memory.c | 135 + .../libtomcrypt/src/encauth/eax/eax_done.c | 121 + .../libtomcrypt/src/encauth/eax/eax_encrypt.c | 78 + .../eax/eax_encrypt_authenticate_memory.c | 109 + .../libtomcrypt/src/encauth/eax/eax_init.c | 171 ++ .../libtomcrypt/src/encauth/eax/eax_test.c | 309 ++ core/lib/libtomcrypt/src/encauth/eax/sub.mk | 8 + .../libtomcrypt/src/encauth/gcm/gcm_add_aad.c | 151 + .../libtomcrypt/src/encauth/gcm/gcm_add_iv.c | 121 + .../libtomcrypt/src/encauth/gcm/gcm_done.c | 110 + .../libtomcrypt/src/encauth/gcm/gcm_gf_mult.c | 248 ++ .../libtomcrypt/src/encauth/gcm/gcm_init.c | 134 + .../libtomcrypt/src/encauth/gcm/gcm_memory.c | 136 + .../libtomcrypt/src/encauth/gcm/gcm_mult_h.c | 85 + .../libtomcrypt/src/encauth/gcm/gcm_process.c | 179 ++ .../libtomcrypt/src/encauth/gcm/gcm_reset.c | 71 + .../libtomcrypt/src/encauth/gcm/gcm_test.c | 440 +++ core/lib/libtomcrypt/src/encauth/gcm/sub.mk | 10 + .../libtomcrypt/src/encauth/ocb/ocb_decrypt.c | 106 + .../encauth/ocb/ocb_decrypt_verify_memory.c | 113 + .../src/encauth/ocb/ocb_done_decrypt.c | 107 + .../src/encauth/ocb/ocb_done_encrypt.c | 73 + .../libtomcrypt/src/encauth/ocb/ocb_encrypt.c | 99 + .../ocb/ocb_encrypt_authenticate_memory.c | 111 + .../libtomcrypt/src/encauth/ocb/ocb_init.c | 164 + .../lib/libtomcrypt/src/encauth/ocb/ocb_ntz.c | 69 + .../src/encauth/ocb/ocb_shift_xor.c | 66 + .../libtomcrypt/src/encauth/ocb/ocb_test.c | 264 ++ .../libtomcrypt/src/encauth/ocb/s_ocb_done.c | 175 ++ core/lib/libtomcrypt/src/encauth/ocb/sub.mk | 11 + core/lib/libtomcrypt/src/encauth/sub.mk | 4 + .../libtomcrypt/src/hashes/helper/hash_file.c | 84 + .../src/hashes/helper/hash_filehandle.c | 98 + .../src/hashes/helper/hash_memory.c | 96 + .../src/hashes/helper/hash_memory_multi.c | 114 + core/lib/libtomcrypt/src/hashes/helper/sub.mk | 6 + core/lib/libtomcrypt/src/hashes/md5.c | 395 +++ core/lib/libtomcrypt/src/hashes/sha1.c | 315 ++ core/lib/libtomcrypt/src/hashes/sha2/sha224.c | 158 + core/lib/libtomcrypt/src/hashes/sha2/sha256.c | 363 +++ core/lib/libtomcrypt/src/hashes/sha2/sha384.c | 165 + core/lib/libtomcrypt/src/hashes/sha2/sha512.c | 342 +++ core/lib/libtomcrypt/src/hashes/sha2/sub.mk | 4 + core/lib/libtomcrypt/src/hashes/sub.mk | 5 + core/lib/libtomcrypt/src/mac/hmac/hmac_done.c | 136 + core/lib/libtomcrypt/src/mac/hmac/hmac_file.c | 120 + core/lib/libtomcrypt/src/mac/hmac/hmac_init.c | 139 + .../libtomcrypt/src/mac/hmac/hmac_memory.c | 115 + .../src/mac/hmac/hmac_memory_multi.c | 119 + .../libtomcrypt/src/mac/hmac/hmac_process.c | 70 + core/lib/libtomcrypt/src/mac/hmac/hmac_test.c | 343 +++ core/lib/libtomcrypt/src/mac/hmac/sub.mk | 9 + core/lib/libtomcrypt/src/mac/omac/omac_done.c | 113 + core/lib/libtomcrypt/src/mac/omac/omac_file.c | 110 + core/lib/libtomcrypt/src/mac/omac/omac_init.c | 128 + .../libtomcrypt/src/mac/omac/omac_memory.c | 112 + .../src/mac/omac/omac_memory_multi.c | 117 + .../libtomcrypt/src/mac/omac/omac_process.c | 116 + core/lib/libtomcrypt/src/mac/omac/omac_test.c | 137 + core/lib/libtomcrypt/src/mac/omac/sub.mk | 9 + core/lib/libtomcrypt/src/mac/pmac/pmac_done.c | 101 + core/lib/libtomcrypt/src/mac/pmac/pmac_file.c | 111 + core/lib/libtomcrypt/src/mac/pmac/pmac_init.c | 174 ++ .../libtomcrypt/src/mac/pmac/pmac_memory.c | 101 + .../src/mac/pmac/pmac_memory_multi.c | 116 + core/lib/libtomcrypt/src/mac/pmac/pmac_ntz.c | 66 + .../libtomcrypt/src/mac/pmac/pmac_process.c | 127 + .../libtomcrypt/src/mac/pmac/pmac_shift_xor.c | 71 + core/lib/libtomcrypt/src/mac/pmac/pmac_test.c | 192 ++ core/lib/libtomcrypt/src/mac/pmac/sub.mk | 11 + core/lib/libtomcrypt/src/mac/sub.mk | 4 + core/lib/libtomcrypt/src/mac/xcbc/sub.mk | 9 + core/lib/libtomcrypt/src/mac/xcbc/xcbc_done.c | 104 + core/lib/libtomcrypt/src/mac/xcbc/xcbc_file.c | 110 + core/lib/libtomcrypt/src/mac/xcbc/xcbc_init.c | 135 + .../libtomcrypt/src/mac/xcbc/xcbc_memory.c | 98 + .../src/mac/xcbc/xcbc_memory_multi.c | 117 + .../libtomcrypt/src/mac/xcbc/xcbc_process.c | 102 + core/lib/libtomcrypt/src/mac/xcbc/xcbc_test.c | 155 + core/lib/libtomcrypt/src/math/multi.c | 88 + core/lib/libtomcrypt/src/math/rand_prime.c | 114 + core/lib/libtomcrypt/src/math/sub.mk | 2 + .../src/misc/base64/base64_decode.c | 131 + .../src/misc/base64/base64_encode.c | 108 + core/lib/libtomcrypt/src/misc/base64/sub.mk | 2 + core/lib/libtomcrypt/src/misc/burn_stack.c | 61 + core/lib/libtomcrypt/src/misc/crypt/crypt.c | 400 +++ .../libtomcrypt/src/misc/crypt/crypt_argchk.c | 57 + .../src/misc/crypt/crypt_cipher_descriptor.c | 54 + .../src/misc/crypt/crypt_cipher_is_valid.c | 63 + .../src/misc/crypt/crypt_find_cipher.c | 68 + .../src/misc/crypt/crypt_find_cipher_any.c | 77 + .../src/misc/crypt/crypt_find_cipher_id.c | 67 + .../src/misc/crypt/crypt_find_hash.c | 67 + .../src/misc/crypt/crypt_find_hash_any.c | 76 + .../src/misc/crypt/crypt_find_hash_id.c | 67 + .../src/misc/crypt/crypt_find_hash_oid.c | 62 + .../src/misc/crypt/crypt_find_prng.c | 68 + .../libtomcrypt/src/misc/crypt/crypt_fsa.c | 86 + .../src/misc/crypt/crypt_hash_descriptor.c | 54 + .../src/misc/crypt/crypt_hash_is_valid.c | 63 + .../src/misc/crypt/crypt_prng_descriptor.c | 53 + .../src/misc/crypt/crypt_prng_is_valid.c | 63 + .../src/misc/crypt/crypt_register_cipher.c | 81 + .../src/misc/crypt/crypt_register_hash.c | 81 + .../src/misc/crypt/crypt_register_prng.c | 81 + .../src/misc/crypt/crypt_unregister_cipher.c | 72 + .../src/misc/crypt/crypt_unregister_hash.c | 71 + .../src/misc/crypt/crypt_unregister_prng.c | 71 + core/lib/libtomcrypt/src/misc/crypt/sub.mk | 22 + .../libtomcrypt/src/misc/error_to_string.c | 101 + .../lib/libtomcrypt/src/misc/pkcs5/pkcs_5_1.c | 133 + .../lib/libtomcrypt/src/misc/pkcs5/pkcs_5_2.c | 156 + core/lib/libtomcrypt/src/misc/pkcs5/sub.mk | 2 + core/lib/libtomcrypt/src/misc/sub.mk | 6 + core/lib/libtomcrypt/src/misc/zeromem.c | 61 + .../libtomcrypt/src/modes/cbc/cbc_decrypt.c | 124 + core/lib/libtomcrypt/src/modes/cbc/cbc_done.c | 69 + .../libtomcrypt/src/modes/cbc/cbc_encrypt.c | 125 + .../lib/libtomcrypt/src/modes/cbc/cbc_getiv.c | 73 + .../lib/libtomcrypt/src/modes/cbc/cbc_setiv.c | 71 + .../lib/libtomcrypt/src/modes/cbc/cbc_start.c | 89 + core/lib/libtomcrypt/src/modes/cbc/sub.mk | 6 + .../libtomcrypt/src/modes/cfb/cfb_decrypt.c | 94 + core/lib/libtomcrypt/src/modes/cfb/cfb_done.c | 69 + .../libtomcrypt/src/modes/cfb/cfb_encrypt.c | 92 + .../lib/libtomcrypt/src/modes/cfb/cfb_getiv.c | 73 + .../lib/libtomcrypt/src/modes/cfb/cfb_setiv.c | 79 + .../lib/libtomcrypt/src/modes/cfb/cfb_start.c | 92 + core/lib/libtomcrypt/src/modes/cfb/sub.mk | 6 + .../libtomcrypt/src/modes/ctr/ctr_decrypt.c | 69 + core/lib/libtomcrypt/src/modes/ctr/ctr_done.c | 69 + .../libtomcrypt/src/modes/ctr/ctr_encrypt.c | 139 + .../lib/libtomcrypt/src/modes/ctr/ctr_getiv.c | 73 + .../lib/libtomcrypt/src/modes/ctr/ctr_setiv.c | 83 + .../lib/libtomcrypt/src/modes/ctr/ctr_start.c | 128 + core/lib/libtomcrypt/src/modes/ctr/ctr_test.c | 109 + core/lib/libtomcrypt/src/modes/ctr/sub.mk | 7 + .../libtomcrypt/src/modes/ecb/ecb_decrypt.c | 88 + core/lib/libtomcrypt/src/modes/ecb/ecb_done.c | 69 + .../libtomcrypt/src/modes/ecb/ecb_encrypt.c | 88 + .../lib/libtomcrypt/src/modes/ecb/ecb_start.c | 75 + core/lib/libtomcrypt/src/modes/ecb/sub.mk | 4 + .../lib/libtomcrypt/src/modes/f8/f8_decrypt.c | 70 + core/lib/libtomcrypt/src/modes/f8/f8_done.c | 69 + .../lib/libtomcrypt/src/modes/f8/f8_encrypt.c | 130 + core/lib/libtomcrypt/src/modes/f8/f8_getiv.c | 73 + core/lib/libtomcrypt/src/modes/f8/f8_setiv.c | 79 + core/lib/libtomcrypt/src/modes/f8/f8_start.c | 125 + .../libtomcrypt/src/modes/f8/f8_test_mode.c | 103 + core/lib/libtomcrypt/src/modes/f8/sub.mk | 7 + .../libtomcrypt/src/modes/lrw/lrw_decrypt.c | 78 + core/lib/libtomcrypt/src/modes/lrw/lrw_done.c | 69 + .../libtomcrypt/src/modes/lrw/lrw_encrypt.c | 77 + .../lib/libtomcrypt/src/modes/lrw/lrw_getiv.c | 72 + .../libtomcrypt/src/modes/lrw/lrw_process.c | 147 + .../lib/libtomcrypt/src/modes/lrw/lrw_setiv.c | 106 + .../lib/libtomcrypt/src/modes/lrw/lrw_start.c | 130 + core/lib/libtomcrypt/src/modes/lrw/lrw_test.c | 163 + core/lib/libtomcrypt/src/modes/lrw/sub.mk | 8 + .../libtomcrypt/src/modes/ofb/ofb_decrypt.c | 70 + core/lib/libtomcrypt/src/modes/ofb/ofb_done.c | 69 + .../libtomcrypt/src/modes/ofb/ofb_encrypt.c | 87 + .../lib/libtomcrypt/src/modes/ofb/ofb_getiv.c | 73 + .../lib/libtomcrypt/src/modes/ofb/ofb_setiv.c | 79 + .../lib/libtomcrypt/src/modes/ofb/ofb_start.c | 87 + core/lib/libtomcrypt/src/modes/ofb/sub.mk | 6 + core/lib/libtomcrypt/src/modes/sub.mk | 8 + core/lib/libtomcrypt/src/modes/xts/sub.mk | 6 + .../libtomcrypt/src/modes/xts/xts_decrypt.c | 167 + core/lib/libtomcrypt/src/modes/xts/xts_done.c | 61 + .../libtomcrypt/src/modes/xts/xts_encrypt.c | 168 + core/lib/libtomcrypt/src/modes/xts/xts_init.c | 95 + .../libtomcrypt/src/modes/xts/xts_mult_x.c | 68 + core/lib/libtomcrypt/src/modes/xts/xts_test.c | 225 ++ core/lib/libtomcrypt/src/mpa_desc.c | 644 ++++ .../pk/asn1/der/bit/der_decode_bit_string.c | 129 + .../pk/asn1/der/bit/der_encode_bit_string.c | 116 + .../pk/asn1/der/bit/der_length_bit_string.c | 81 + .../libtomcrypt/src/pk/asn1/der/bit/sub.mk | 3 + .../pk/asn1/der/boolean/der_decode_boolean.c | 74 + .../pk/asn1/der/boolean/der_encode_boolean.c | 78 + .../pk/asn1/der/boolean/der_length_boolean.c | 62 + .../src/pk/asn1/der/boolean/sub.mk | 3 + .../pk/asn1/der/choice/der_decode_choice.c | 209 ++ .../libtomcrypt/src/pk/asn1/der/choice/sub.mk | 1 + .../pk/asn1/der/ia5/der_decode_ia5_string.c | 123 + .../pk/asn1/der/ia5/der_encode_ia5_string.c | 112 + .../pk/asn1/der/ia5/der_length_ia5_string.c | 221 ++ .../libtomcrypt/src/pk/asn1/der/ia5/sub.mk | 3 + .../pk/asn1/der/integer/der_decode_integer.c | 137 + .../pk/asn1/der/integer/der_encode_integer.c | 157 + .../pk/asn1/der/integer/der_length_integer.c | 109 + .../src/pk/asn1/der/integer/sub.mk | 3 + .../der_decode_object_identifier.c | 126 + .../der_encode_object_identifier.c | 138 + .../der_length_object_identifier.c | 116 + .../src/pk/asn1/der/object_identifier/sub.mk | 3 + .../asn1/der/octet/der_decode_octet_string.c | 118 + .../asn1/der/octet/der_encode_octet_string.c | 113 + .../asn1/der/octet/der_length_octet_string.c | 80 + .../libtomcrypt/src/pk/asn1/der/octet/sub.mk | 3 + .../der_decode_printable_string.c | 123 + .../der_encode_printable_string.c | 112 + .../der_length_printable_string.c | 193 ++ .../src/pk/asn1/der/printable_string/sub.mk | 3 + .../der/sequence/der_decode_sequence_ex.c | 314 ++ .../der/sequence/der_decode_sequence_flexi.c | 413 +++ .../der/sequence/der_decode_sequence_multi.c | 166 + .../der/sequence/der_encode_sequence_ex.c | 362 +++ .../der/sequence/der_encode_sequence_multi.c | 165 + .../asn1/der/sequence/der_length_sequence.c | 195 ++ .../pk/asn1/der/sequence/der_sequence_free.c | 92 + .../src/pk/asn1/der/sequence/sub.mk | 7 + .../src/pk/asn1/der/set/der_encode_set.c | 130 + .../src/pk/asn1/der/set/der_encode_setof.c | 189 ++ .../libtomcrypt/src/pk/asn1/der/set/sub.mk | 2 + .../short_integer/der_decode_short_integer.c | 95 + .../short_integer/der_encode_short_integer.c | 124 + .../short_integer/der_length_short_integer.c | 97 + .../src/pk/asn1/der/short_integer/sub.mk | 3 + core/lib/libtomcrypt/src/pk/asn1/der/sub.mk | 13 + .../pk/asn1/der/utctime/der_decode_utctime.c | 156 + .../pk/asn1/der/utctime/der_encode_utctime.c | 110 + .../pk/asn1/der/utctime/der_length_utctime.c | 73 + .../src/pk/asn1/der/utctime/sub.mk | 3 + .../pk/asn1/der/utf8/der_decode_utf8_string.c | 138 + .../pk/asn1/der/utf8/der_encode_utf8_string.c | 133 + .../pk/asn1/der/utf8/der_length_utf8_string.c | 110 + .../libtomcrypt/src/pk/asn1/der/utf8/sub.mk | 4 + core/lib/libtomcrypt/src/pk/asn1/sub.mk | 1 + core/lib/libtomcrypt/src/pk/dh/dh.c | 217 ++ core/lib/libtomcrypt/src/pk/dh/sub.mk | 2 + .../libtomcrypt/src/pk/dsa/dsa_decrypt_key.c | 165 + .../libtomcrypt/src/pk/dsa/dsa_encrypt_key.c | 161 + core/lib/libtomcrypt/src/pk/dsa/dsa_export.c | 99 + core/lib/libtomcrypt/src/pk/dsa/dsa_free.c | 61 + core/lib/libtomcrypt/src/pk/dsa/dsa_import.c | 117 + .../lib/libtomcrypt/src/pk/dsa/dsa_make_key.c | 164 + .../src/pk/dsa/dsa_shared_secret.c | 98 + .../libtomcrypt/src/pk/dsa/dsa_sign_hash.c | 183 ++ .../libtomcrypt/src/pk/dsa/dsa_verify_hash.c | 153 + .../libtomcrypt/src/pk/dsa/dsa_verify_key.c | 127 + core/lib/libtomcrypt/src/pk/dsa/sub.mk | 10 + core/lib/libtomcrypt/src/pk/ecc/ecc.c | 154 + .../src/pk/ecc/ecc_ansi_x963_export.c | 99 + .../src/pk/ecc/ecc_ansi_x963_import.c | 131 + .../libtomcrypt/src/pk/ecc/ecc_decrypt_key.c | 176 ++ .../libtomcrypt/src/pk/ecc/ecc_encrypt_key.c | 162 + core/lib/libtomcrypt/src/pk/ecc/ecc_export.c | 108 + core/lib/libtomcrypt/src/pk/ecc/ecc_free.c | 66 + .../lib/libtomcrypt/src/pk/ecc/ecc_get_size.c | 70 + core/lib/libtomcrypt/src/pk/ecc/ecc_import.c | 198 ++ .../lib/libtomcrypt/src/pk/ecc/ecc_make_key.c | 156 + .../src/pk/ecc/ecc_shared_secret.c | 121 + .../libtomcrypt/src/pk/ecc/ecc_sign_hash.c | 140 + core/lib/libtomcrypt/src/pk/ecc/ecc_sizes.c | 74 + core/lib/libtomcrypt/src/pk/ecc/ecc_test.c | 121 + .../libtomcrypt/src/pk/ecc/ecc_verify_hash.c | 191 ++ .../src/pk/ecc/ltc_ecc_is_valid_idx.c | 72 + core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_map.c | 102 + .../libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c | 234 ++ .../libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c | 450 +++ .../src/pk/ecc/ltc_ecc_mulmod_timing.c | 193 ++ .../libtomcrypt/src/pk/ecc/ltc_ecc_points.c | 86 + .../src/pk/ecc/ltc_ecc_projective_add_point.c | 222 ++ .../src/pk/ecc/ltc_ecc_projective_dbl_point.c | 173 ++ core/lib/libtomcrypt/src/pk/ecc/sub.mk | 23 + .../libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c | 78 + .../libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c | 135 + .../src/pk/pkcs1/pkcs_1_oaep_decode.c | 216 ++ .../src/pk/pkcs1/pkcs_1_oaep_encode.c | 200 ++ .../libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c | 63 + .../src/pk/pkcs1/pkcs_1_pss_decode.c | 204 ++ .../src/pk/pkcs1/pkcs_1_pss_encode.c | 202 ++ .../src/pk/pkcs1/pkcs_1_v1_5_decode.c | 137 + .../src/pk/pkcs1/pkcs_1_v1_5_encode.c | 138 + core/lib/libtomcrypt/src/pk/pkcs1/sub.mk | 9 + .../libtomcrypt/src/pk/rsa/rsa_decrypt_key.c | 132 + .../libtomcrypt/src/pk/rsa/rsa_encrypt_key.c | 129 + core/lib/libtomcrypt/src/pk/rsa/rsa_export.c | 96 + core/lib/libtomcrypt/src/pk/rsa/rsa_exptmod.c | 154 + core/lib/libtomcrypt/src/pk/rsa/rsa_free.c | 61 + core/lib/libtomcrypt/src/pk/rsa/rsa_import.c | 170 ++ .../lib/libtomcrypt/src/pk/rsa/rsa_make_key.c | 139 + .../libtomcrypt/src/pk/rsa/rsa_sign_hash.c | 161 + .../libtomcrypt/src/pk/rsa/rsa_verify_hash.c | 194 ++ core/lib/libtomcrypt/src/pk/rsa/sub.mk | 9 + core/lib/libtomcrypt/src/pk/sub.mk | 6 + .../lib/libtomcrypt/src/prngs/rng_get_bytes.c | 175 ++ .../lib/libtomcrypt/src/prngs/rng_make_prng.c | 96 + core/lib/libtomcrypt/src/prngs/sprng.c | 163 + core/lib/libtomcrypt/src/prngs/sub.mk | 6 + core/lib/libtomcrypt/src/prngs/yarrow.c | 389 +++ core/lib/libtomcrypt/src/sub.mk | 18 + core/lib/libtomcrypt/src/tee_ltc_wrapper.c | 403 +++ core/lib/libtomcrypt/sub.mk | 3 + core/lib/libtomcrypt/test/base64_test.c | 24 + core/lib/libtomcrypt/test/cipher_hash_test.c | 45 + core/lib/libtomcrypt/test/der_tests.c | 854 ++++++ core/lib/libtomcrypt/test/dsa_test.c | 82 + core/lib/libtomcrypt/test/ecc_test.c | 252 ++ core/lib/libtomcrypt/test/mac_test.c | 41 + core/lib/libtomcrypt/test/modes_test.c | 119 + core/lib/libtomcrypt/test/pkcs_1_test.c | 93 + core/lib/libtomcrypt/test/rsa_test.c | 388 +++ core/lib/libtomcrypt/test/store_test.c | 78 + core/lib/libtomcrypt/test/test.c | 77 + core/lib/libtomcrypt/test/test_driver.c | 15 + core/lib/libtomcrypt/test/tomcrypt_test.h | 84 + core/lib/libtomcrypt/test/unit_test.c | 1653 ++++++++++ core/lib/libtomcrypt/test/x86_prof.c | 1436 +++++++++ core/mm/sub.mk | 0 core/sub.mk | 4 + core/tee/sub.mk | 31 + core/tee/tee_acipher.c | 508 +++ core/tee/tee_authenc.c | 450 +++ core/tee/tee_cipher.c | 496 +++ core/tee/tee_fs.c | 553 ++++ core/tee/tee_hash.c | 204 ++ core/tee/tee_mac.c | 313 ++ core/tee/tee_obj.c | 74 + core/tee/tee_pobj.c | 156 + core/tee/tee_rpmb.c | 1216 ++++++++ core/tee/tee_rpmb_fs.c | 598 ++++ core/tee/tee_svc.c | 875 ++++++ core/tee/tee_svc_cryp.c | 2711 +++++++++++++++++ core/tee/tee_svc_storage.c | 1098 +++++++ core/tee/tee_time_generic.c | 206 ++ documentation/build_system.md | 28 + documentation/file_structure.md | 60 + lib/libmpa/arch/arm32/sub.mk | 1 + lib/libmpa/include/mpa.h | 266 ++ lib/libmpa/include/mpa_assert.h | 68 + lib/libmpa/include/mpa_debug.h | 101 + lib/libmpa/include/mpalib.h | 409 +++ lib/libmpa/include/mpalib_config.h | 125 + lib/libmpa/mpa_addsub.c | 581 ++++ lib/libmpa/mpa_arm_asm.s | 428 +++ lib/libmpa/mpa_cmp.c | 179 ++ lib/libmpa/mpa_conv.c | 100 + lib/libmpa/mpa_debug.c | 110 + lib/libmpa/mpa_div.c | 428 +++ lib/libmpa/mpa_expmod.c | 97 + lib/libmpa/mpa_gcd.c | 394 +++ lib/libmpa/mpa_init.c | 77 + lib/libmpa/mpa_io.c | 626 ++++ lib/libmpa/mpa_mem_static.c | 130 + lib/libmpa/mpa_misc.c | 197 ++ lib/libmpa/mpa_modulus.c | 171 ++ lib/libmpa/mpa_montgomery.c | 282 ++ lib/libmpa/mpa_mul.c | 239 ++ lib/libmpa/mpa_primetable.h | 242 ++ lib/libmpa/mpa_primetest.c | 326 ++ lib/libmpa/mpa_random.c | 89 + lib/libmpa/mpa_shift.c | 244 ++ lib/libmpa/sub.mk | 42 + lib/libutee/abort.c | 35 + lib/libutee/arch/arm32/bget.c | 1628 ++++++++++ lib/libutee/arch/arm32/bget.doc | 338 ++ lib/libutee/arch/arm32/bget.h | 43 + lib/libutee/arch/arm32/bget_malloc.c | 269 ++ lib/libutee/arch/arm32/bget_malloc.h | 60 + lib/libutee/arch/arm32/sub.mk | 9 + lib/libutee/arch/arm32/user_ta_entry.c | 228 ++ lib/libutee/arch/arm32/utee_misc.c | 72 + lib/libutee/arch/arm32/utee_syscalls_asm.S | 172 ++ lib/libutee/assert.c | 39 + lib/libutee/base64.c | 149 + lib/libutee/base64.h | 37 + lib/libutee/errno.c | 29 + lib/libutee/include/tee_api.h | 454 +++ lib/libutee/include/tee_api_defines.h | 266 ++ lib/libutee/include/tee_api_types.h | 183 ++ lib/libutee/include/tee_arith_internal.h | 89 + lib/libutee/include/tee_internal_api.h | 42 + .../include/tee_internal_api_extensions.h | 45 + lib/libutee/include/tee_syscall_numbers.h | 90 + lib/libutee/include/tee_ta_api.h | 221 ++ lib/libutee/include/tee_trace.h | 72 + lib/libutee/include/tee_uta_trace.h | 152 + lib/libutee/include/user_ta_header.h | 149 + lib/libutee/include/utee_defines.h | 216 ++ lib/libutee/include/utee_syscalls.h | 190 ++ lib/libutee/include/utee_types.h | 48 + lib/libutee/sub.mk | 25 + lib/libutee/ta_trace.c | 186 ++ lib/libutee/tee_api.c | 223 ++ lib/libutee/tee_api_arith.c | 581 ++++ lib/libutee/tee_api_objects.c | 529 ++++ lib/libutee/tee_api_operations.c | 1142 +++++++ lib/libutee/tee_api_property.c | 555 ++++ lib/libutee/tee_user_mem.c | 538 ++++ lib/libutee/tee_user_mem.h | 45 + lib/libutee/utee_misc.h | 38 + lib/libutils/ext/include/string_ext.h | 46 + lib/libutils/ext/strlcat.c | 75 + lib/libutils/ext/strlcpy.c | 68 + lib/libutils/ext/sub.mk | 4 + lib/libutils/isoc/arch/arm32/aeabi_divmod.c | 244 ++ .../isoc/arch/arm32/aeabi_divmod_asm.S | 51 + lib/libutils/isoc/arch/arm32/sub.mk | 2 + lib/libutils/isoc/dlmalloc.c | 2475 +++++++++++++++ lib/libutils/isoc/dlmalloc.h | 941 ++++++ lib/libutils/isoc/include/assert.h | 41 + lib/libutils/isoc/include/ctype.h | 30 + lib/libutils/isoc/include/inttypes.h | 71 + lib/libutils/isoc/include/limits.h | 74 + lib/libutils/isoc/include/malloc.h | 95 + lib/libutils/isoc/include/memory.h | 31 + lib/libutils/isoc/include/signal.h | 30 + lib/libutils/isoc/include/stdint.h | 96 + lib/libutils/isoc/include/stdio.h | 44 + lib/libutils/isoc/include/stdlib.h | 42 + lib/libutils/isoc/include/string.h | 52 + lib/libutils/isoc/include/sys/cdefs.h | 44 + lib/libutils/isoc/include/sys/queue.h | 699 +++++ lib/libutils/isoc/include/sys/types.h | 39 + lib/libutils/isoc/include/time.h | 32 + lib/libutils/isoc/include/unistd.h | 36 + lib/libutils/isoc/include/wchar.h | 30 + lib/libutils/isoc/malloc_wrapper.c | 497 +++ lib/libutils/isoc/newlib/_ansi.h | 128 + lib/libutils/isoc/newlib/memchr.c | 158 + lib/libutils/isoc/newlib/memcmp.c | 135 + lib/libutils/isoc/newlib/memcpy.c | 134 + lib/libutils/isoc/newlib/memmove.c | 156 + lib/libutils/isoc/newlib/memset.c | 128 + lib/libutils/isoc/newlib/strcmp.c | 140 + lib/libutils/isoc/newlib/strlen.c | 118 + lib/libutils/isoc/newlib/strnlen.c | 80 + lib/libutils/isoc/newlib/sub.mk | 26 + lib/libutils/isoc/qsort.c | 150 + lib/libutils/isoc/snprintf.c | 545 ++++ lib/libutils/isoc/stack_check.c | 36 + lib/libutils/isoc/strdup.c | 38 + lib/libutils/isoc/strndup.c | 40 + lib/libutils/isoc/sub.mk | 20 + lib/libutils/sub.mk | 2 + mk/cleanvars.mk | 10 + mk/compile.mk | 114 + mk/config.mk | 39 + mk/gcc.mk | 17 + mk/lib.mk | 30 + mk/subdir.mk | 68 + scripts/fixdep | 19 + ta/arch/arm32/link.mk | 43 + ta/arch/arm32/user_ta_elf_arm.lds | 153 + ta/arch/arm32/user_ta_header.c | 122 + ta/mk/ta_dev_kit.mk | 58 + ta/ta.mk | 79 + 616 files changed, 99101 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 Makefile create mode 100755 Notice.md create mode 100644 core/arch/arm32/include/arm32.h create mode 100644 core/arch/arm32/include/arm32_macros.S create mode 100644 core/arch/arm32/include/kernel/arch_debug.h create mode 100644 core/arch/arm32/include/kernel/asc.h create mode 100644 core/arch/arm32/include/kernel/kta_types.h create mode 100644 core/arch/arm32/include/kernel/misc.h create mode 100644 core/arch/arm32/include/kernel/tee_l2cc_mutex.h create mode 100644 core/arch/arm32/include/kernel/tee_misc.h create mode 100644 core/arch/arm32/include/kernel/thread.h create mode 100644 core/arch/arm32/include/kernel/thread_defs.h create mode 100644 core/arch/arm32/include/kernel/tz_proc.h create mode 100644 core/arch/arm32/include/kernel/tz_proc_def.h create mode 100644 core/arch/arm32/include/kernel/tz_ssvce.h create mode 100644 core/arch/arm32/include/kernel/tz_ssvce_def.h create mode 100644 core/arch/arm32/include/mm/core_memprot.h create mode 100644 core/arch/arm32/include/mm/core_mmu.h create mode 100644 core/arch/arm32/include/mm/tee_mm_def.h create mode 100644 core/arch/arm32/include/mm/tee_mmu_defs.h create mode 100644 core/arch/arm32/include/mm/tee_pager_defines.h create mode 100644 core/arch/arm32/include/mm/tee_pager_unpg.h create mode 100644 core/arch/arm32/include/sm/sm.h create mode 100644 core/arch/arm32/include/sm/sm_defs.h create mode 100644 core/arch/arm32/include/sm/tee_mon.h create mode 100644 core/arch/arm32/include/sm/teesmc.h create mode 100644 core/arch/arm32/include/sm/teesmc_st.h create mode 100644 core/arch/arm32/include/tee/entry.h create mode 100644 core/arch/arm32/kernel/chip_services.c create mode 100644 core/arch/arm32/kernel/misc.S create mode 100644 core/arch/arm32/kernel/sub.mk create mode 100644 core/arch/arm32/kernel/tee_core_trace.c create mode 100644 core/arch/arm32/kernel/tee_l2cc_mutex.c create mode 100644 core/arch/arm32/kernel/tee_misc.c create mode 100644 core/arch/arm32/kernel/tee_sleep_services.c create mode 100644 core/arch/arm32/kernel/tee_ta_manager.c create mode 100644 core/arch/arm32/kernel/tee_time.c create mode 100644 core/arch/arm32/kernel/tee_time_unpg.c create mode 100644 core/arch/arm32/kernel/thread.c create mode 100644 core/arch/arm32/kernel/thread_asm.S create mode 100644 core/arch/arm32/kernel/thread_private.h create mode 100644 core/arch/arm32/kernel/tz_proc.S create mode 100644 core/arch/arm32/kernel/tz_ssvce.S create mode 100644 core/arch/arm32/mm/core_mmu.c create mode 100644 core/arch/arm32/mm/kta_table_unpg_asm.S create mode 100644 core/arch/arm32/mm/sub.mk create mode 100644 core/arch/arm32/mm/tee_mm.c create mode 100644 core/arch/arm32/mm/tee_mm_unpg.c create mode 100644 core/arch/arm32/mm/tee_mmu.c create mode 100644 core/arch/arm32/mm/tee_mmu_unpg.c create mode 100644 core/arch/arm32/mm/tee_mmu_unpg_asm.S create mode 100644 core/arch/arm32/mm/tee_pager.c create mode 100644 core/arch/arm32/mm/tee_pager_unpg.c create mode 100644 core/arch/arm32/mm/tee_pager_unpg_asm.S create mode 100644 core/arch/arm32/plat-orly2/.gitignore create mode 100644 core/arch/arm32/plat-orly2/asc.S create mode 100644 core/arch/arm32/plat-orly2/conf.mk create mode 100644 core/arch/arm32/plat-orly2/core_bootcfg.c create mode 100644 core/arch/arm32/plat-orly2/core_chip.c create mode 100644 core/arch/arm32/plat-orly2/link.mk create mode 100644 core/arch/arm32/plat-orly2/main.c create mode 100644 core/arch/arm32/plat-orly2/rng_support.c create mode 100644 core/arch/arm32/plat-orly2/sub.mk create mode 100644 core/arch/arm32/plat-orly2/system_config.in create mode 100644 core/arch/arm32/plat-orly2/tee_common_otp.c create mode 100644 core/arch/arm32/plat-orly2/tz-template.lds create mode 100644 core/arch/arm32/plat-orly2/tz_a9init.S create mode 100644 core/arch/arm32/plat-orly2/tz_sinit.S create mode 100644 core/arch/arm32/sm/sm.c create mode 100644 core/arch/arm32/sm/sm_asm.S create mode 100644 core/arch/arm32/sm/sub.mk create mode 100644 core/arch/arm32/sm/tee_mon.c create mode 100644 core/arch/arm32/sta/core_dirty_tests.c create mode 100644 core/arch/arm32/sta/core_dirty_tests.h create mode 100644 core/arch/arm32/sta/sta_helloworld.c create mode 100644 core/arch/arm32/sta/sub.mk create mode 100644 core/arch/arm32/tee/entry.c create mode 100644 core/arch/arm32/tee/sub.mk create mode 100644 core/arch/arm32/tee/tee_svc_asm.S create mode 100644 core/core.mk create mode 100644 core/default_signing.properties create mode 100644 core/drivers/gic.c create mode 100644 core/drivers/sub.mk create mode 100644 core/drivers/uart.c create mode 100644 core/include/asm.S create mode 100644 core/include/core_serviceid.h create mode 100644 core/include/drivers/gic.h create mode 100644 core/include/drivers/uart.h create mode 100644 core/include/io.h create mode 100644 core/include/kernel/chip_services.h create mode 100644 core/include/kernel/kernel.h create mode 100644 core/include/kernel/kta_mem.h create mode 100644 core/include/kernel/panic.h create mode 100644 core/include/kernel/tee_common.h create mode 100644 core/include/kernel/tee_common_otp.h create mode 100644 core/include/kernel/tee_common_unpg.h create mode 100644 core/include/kernel/tee_compat.h create mode 100644 core/include/kernel/tee_core_trace.h create mode 100644 core/include/kernel/tee_customer_part.h create mode 100644 core/include/kernel/tee_dispatch.h create mode 100644 core/include/kernel/tee_kta_trace.h create mode 100644 core/include/kernel/tee_misc_unpg.h create mode 100644 core/include/kernel/tee_rpc.h create mode 100644 core/include/kernel/tee_rpc_types.h create mode 100644 core/include/kernel/tee_sleep_services.h create mode 100644 core/include/kernel/tee_ta.h create mode 100644 core/include/kernel/tee_ta_manager.h create mode 100644 core/include/kernel/tee_ta_manager_unpg.h create mode 100644 core/include/kernel/tee_ta_static.h create mode 100644 core/include/kernel/tee_time.h create mode 100644 core/include/kernel/tee_time_unpg.h create mode 100644 core/include/mm/tee_mm.h create mode 100644 core/include/mm/tee_mm_unpg.h create mode 100644 core/include/mm/tee_mmu.h create mode 100644 core/include/mm/tee_mmu_io.h create mode 100644 core/include/mm/tee_mmu_types.h create mode 100644 core/include/mm/tee_mmu_unpg.h create mode 100644 core/include/rng_support.h create mode 100644 core/include/tee/tee_acipher.h create mode 100644 core/include/tee/tee_authenc.h create mode 100644 core/include/tee/tee_cipher.h create mode 100644 core/include/tee/tee_fs.h create mode 100644 core/include/tee/tee_fs_defs.h create mode 100644 core/include/tee/tee_hash.h create mode 100644 core/include/tee/tee_mac.h create mode 100644 core/include/tee/tee_obj.h create mode 100644 core/include/tee/tee_pobj.h create mode 100644 core/include/tee/tee_rpmb.h create mode 100644 core/include/tee/tee_rpmb_fs.h create mode 100644 core/include/tee/tee_svc.h create mode 100644 core/include/tee/tee_svc_cryp.h create mode 100644 core/include/tee/tee_svc_storage.h create mode 100644 core/kernel/assert.c create mode 100644 core/kernel/panic.c create mode 100644 core/kernel/sub.mk create mode 100644 core/kernel/tee_compat.c create mode 100644 core/kernel/tee_dispatch.c create mode 100644 core/kernel/tee_kta_trace.c create mode 100644 core/kernel/tee_ta_manager_unpg.c create mode 100644 core/lib/libtomcrypt/include/tee_ltc_wrapper.h create mode 100644 core/lib/libtomcrypt/include/tomcrypt.h create mode 100644 core/lib/libtomcrypt/include/tomcrypt_argchk.h create mode 100644 core/lib/libtomcrypt/include/tomcrypt_cfg.h create mode 100644 core/lib/libtomcrypt/include/tomcrypt_cipher.h create mode 100644 core/lib/libtomcrypt/include/tomcrypt_custom.h create mode 100644 core/lib/libtomcrypt/include/tomcrypt_hash.h create mode 100644 core/lib/libtomcrypt/include/tomcrypt_mac.h create mode 100644 core/lib/libtomcrypt/include/tomcrypt_macros.h create mode 100644 core/lib/libtomcrypt/include/tomcrypt_math.h create mode 100644 core/lib/libtomcrypt/include/tomcrypt_misc.h create mode 100644 core/lib/libtomcrypt/include/tomcrypt_mpa.h create mode 100644 core/lib/libtomcrypt/include/tomcrypt_pk.h create mode 100644 core/lib/libtomcrypt/include/tomcrypt_pkcs.h create mode 100644 core/lib/libtomcrypt/include/tomcrypt_prng.h create mode 100644 core/lib/libtomcrypt/src/ciphers/aes.c create mode 100644 core/lib/libtomcrypt/src/ciphers/aes_tab.c create mode 100644 core/lib/libtomcrypt/src/ciphers/des.c create mode 100644 core/lib/libtomcrypt/src/ciphers/sub.mk create mode 100644 core/lib/libtomcrypt/src/encauth/ccm/ccm_memory.c create mode 100644 core/lib/libtomcrypt/src/encauth/ccm/ccm_test.c create mode 100644 core/lib/libtomcrypt/src/encauth/ccm/sub.mk create mode 100644 core/lib/libtomcrypt/src/encauth/eax/eax_addheader.c create mode 100644 core/lib/libtomcrypt/src/encauth/eax/eax_decrypt.c create mode 100644 core/lib/libtomcrypt/src/encauth/eax/eax_decrypt_verify_memory.c create mode 100644 core/lib/libtomcrypt/src/encauth/eax/eax_done.c create mode 100644 core/lib/libtomcrypt/src/encauth/eax/eax_encrypt.c create mode 100644 core/lib/libtomcrypt/src/encauth/eax/eax_encrypt_authenticate_memory.c create mode 100644 core/lib/libtomcrypt/src/encauth/eax/eax_init.c create mode 100644 core/lib/libtomcrypt/src/encauth/eax/eax_test.c create mode 100644 core/lib/libtomcrypt/src/encauth/eax/sub.mk create mode 100644 core/lib/libtomcrypt/src/encauth/gcm/gcm_add_aad.c create mode 100644 core/lib/libtomcrypt/src/encauth/gcm/gcm_add_iv.c create mode 100644 core/lib/libtomcrypt/src/encauth/gcm/gcm_done.c create mode 100644 core/lib/libtomcrypt/src/encauth/gcm/gcm_gf_mult.c create mode 100644 core/lib/libtomcrypt/src/encauth/gcm/gcm_init.c create mode 100644 core/lib/libtomcrypt/src/encauth/gcm/gcm_memory.c create mode 100644 core/lib/libtomcrypt/src/encauth/gcm/gcm_mult_h.c create mode 100644 core/lib/libtomcrypt/src/encauth/gcm/gcm_process.c create mode 100644 core/lib/libtomcrypt/src/encauth/gcm/gcm_reset.c create mode 100644 core/lib/libtomcrypt/src/encauth/gcm/gcm_test.c create mode 100644 core/lib/libtomcrypt/src/encauth/gcm/sub.mk create mode 100644 core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt.c create mode 100644 core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt_verify_memory.c create mode 100644 core/lib/libtomcrypt/src/encauth/ocb/ocb_done_decrypt.c create mode 100644 core/lib/libtomcrypt/src/encauth/ocb/ocb_done_encrypt.c create mode 100644 core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt.c create mode 100644 core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt_authenticate_memory.c create mode 100644 core/lib/libtomcrypt/src/encauth/ocb/ocb_init.c create mode 100644 core/lib/libtomcrypt/src/encauth/ocb/ocb_ntz.c create mode 100644 core/lib/libtomcrypt/src/encauth/ocb/ocb_shift_xor.c create mode 100644 core/lib/libtomcrypt/src/encauth/ocb/ocb_test.c create mode 100644 core/lib/libtomcrypt/src/encauth/ocb/s_ocb_done.c create mode 100644 core/lib/libtomcrypt/src/encauth/ocb/sub.mk create mode 100644 core/lib/libtomcrypt/src/encauth/sub.mk create mode 100644 core/lib/libtomcrypt/src/hashes/helper/hash_file.c create mode 100644 core/lib/libtomcrypt/src/hashes/helper/hash_filehandle.c create mode 100644 core/lib/libtomcrypt/src/hashes/helper/hash_memory.c create mode 100644 core/lib/libtomcrypt/src/hashes/helper/hash_memory_multi.c create mode 100644 core/lib/libtomcrypt/src/hashes/helper/sub.mk create mode 100644 core/lib/libtomcrypt/src/hashes/md5.c create mode 100644 core/lib/libtomcrypt/src/hashes/sha1.c create mode 100644 core/lib/libtomcrypt/src/hashes/sha2/sha224.c create mode 100644 core/lib/libtomcrypt/src/hashes/sha2/sha256.c create mode 100644 core/lib/libtomcrypt/src/hashes/sha2/sha384.c create mode 100644 core/lib/libtomcrypt/src/hashes/sha2/sha512.c create mode 100644 core/lib/libtomcrypt/src/hashes/sha2/sub.mk create mode 100644 core/lib/libtomcrypt/src/hashes/sub.mk create mode 100644 core/lib/libtomcrypt/src/mac/hmac/hmac_done.c create mode 100644 core/lib/libtomcrypt/src/mac/hmac/hmac_file.c create mode 100644 core/lib/libtomcrypt/src/mac/hmac/hmac_init.c create mode 100644 core/lib/libtomcrypt/src/mac/hmac/hmac_memory.c create mode 100644 core/lib/libtomcrypt/src/mac/hmac/hmac_memory_multi.c create mode 100644 core/lib/libtomcrypt/src/mac/hmac/hmac_process.c create mode 100644 core/lib/libtomcrypt/src/mac/hmac/hmac_test.c create mode 100644 core/lib/libtomcrypt/src/mac/hmac/sub.mk create mode 100644 core/lib/libtomcrypt/src/mac/omac/omac_done.c create mode 100644 core/lib/libtomcrypt/src/mac/omac/omac_file.c create mode 100644 core/lib/libtomcrypt/src/mac/omac/omac_init.c create mode 100644 core/lib/libtomcrypt/src/mac/omac/omac_memory.c create mode 100644 core/lib/libtomcrypt/src/mac/omac/omac_memory_multi.c create mode 100644 core/lib/libtomcrypt/src/mac/omac/omac_process.c create mode 100644 core/lib/libtomcrypt/src/mac/omac/omac_test.c create mode 100644 core/lib/libtomcrypt/src/mac/omac/sub.mk create mode 100644 core/lib/libtomcrypt/src/mac/pmac/pmac_done.c create mode 100644 core/lib/libtomcrypt/src/mac/pmac/pmac_file.c create mode 100644 core/lib/libtomcrypt/src/mac/pmac/pmac_init.c create mode 100644 core/lib/libtomcrypt/src/mac/pmac/pmac_memory.c create mode 100644 core/lib/libtomcrypt/src/mac/pmac/pmac_memory_multi.c create mode 100644 core/lib/libtomcrypt/src/mac/pmac/pmac_ntz.c create mode 100644 core/lib/libtomcrypt/src/mac/pmac/pmac_process.c create mode 100644 core/lib/libtomcrypt/src/mac/pmac/pmac_shift_xor.c create mode 100644 core/lib/libtomcrypt/src/mac/pmac/pmac_test.c create mode 100644 core/lib/libtomcrypt/src/mac/pmac/sub.mk create mode 100644 core/lib/libtomcrypt/src/mac/sub.mk create mode 100644 core/lib/libtomcrypt/src/mac/xcbc/sub.mk create mode 100644 core/lib/libtomcrypt/src/mac/xcbc/xcbc_done.c create mode 100644 core/lib/libtomcrypt/src/mac/xcbc/xcbc_file.c create mode 100644 core/lib/libtomcrypt/src/mac/xcbc/xcbc_init.c create mode 100644 core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory.c create mode 100644 core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory_multi.c create mode 100644 core/lib/libtomcrypt/src/mac/xcbc/xcbc_process.c create mode 100644 core/lib/libtomcrypt/src/mac/xcbc/xcbc_test.c create mode 100644 core/lib/libtomcrypt/src/math/multi.c create mode 100644 core/lib/libtomcrypt/src/math/rand_prime.c create mode 100644 core/lib/libtomcrypt/src/math/sub.mk create mode 100644 core/lib/libtomcrypt/src/misc/base64/base64_decode.c create mode 100644 core/lib/libtomcrypt/src/misc/base64/base64_encode.c create mode 100644 core/lib/libtomcrypt/src/misc/base64/sub.mk create mode 100644 core/lib/libtomcrypt/src/misc/burn_stack.c create mode 100644 core/lib/libtomcrypt/src/misc/crypt/crypt.c create mode 100644 core/lib/libtomcrypt/src/misc/crypt/crypt_argchk.c create mode 100644 core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_descriptor.c create mode 100644 core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_is_valid.c create mode 100644 core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher.c create mode 100644 core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_any.c create mode 100644 core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_id.c create mode 100644 core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash.c create mode 100644 core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_any.c create mode 100644 core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_id.c create mode 100644 core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_oid.c create mode 100644 core/lib/libtomcrypt/src/misc/crypt/crypt_find_prng.c create mode 100644 core/lib/libtomcrypt/src/misc/crypt/crypt_fsa.c create mode 100644 core/lib/libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c create mode 100644 core/lib/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c create mode 100644 core/lib/libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c create mode 100644 core/lib/libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c create mode 100644 core/lib/libtomcrypt/src/misc/crypt/crypt_register_cipher.c create mode 100644 core/lib/libtomcrypt/src/misc/crypt/crypt_register_hash.c create mode 100644 core/lib/libtomcrypt/src/misc/crypt/crypt_register_prng.c create mode 100644 core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_cipher.c create mode 100644 core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_hash.c create mode 100644 core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_prng.c create mode 100644 core/lib/libtomcrypt/src/misc/crypt/sub.mk create mode 100644 core/lib/libtomcrypt/src/misc/error_to_string.c create mode 100644 core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_1.c create mode 100644 core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_2.c create mode 100644 core/lib/libtomcrypt/src/misc/pkcs5/sub.mk create mode 100644 core/lib/libtomcrypt/src/misc/sub.mk create mode 100644 core/lib/libtomcrypt/src/misc/zeromem.c create mode 100644 core/lib/libtomcrypt/src/modes/cbc/cbc_decrypt.c create mode 100644 core/lib/libtomcrypt/src/modes/cbc/cbc_done.c create mode 100644 core/lib/libtomcrypt/src/modes/cbc/cbc_encrypt.c create mode 100644 core/lib/libtomcrypt/src/modes/cbc/cbc_getiv.c create mode 100644 core/lib/libtomcrypt/src/modes/cbc/cbc_setiv.c create mode 100644 core/lib/libtomcrypt/src/modes/cbc/cbc_start.c create mode 100644 core/lib/libtomcrypt/src/modes/cbc/sub.mk create mode 100644 core/lib/libtomcrypt/src/modes/cfb/cfb_decrypt.c create mode 100644 core/lib/libtomcrypt/src/modes/cfb/cfb_done.c create mode 100644 core/lib/libtomcrypt/src/modes/cfb/cfb_encrypt.c create mode 100644 core/lib/libtomcrypt/src/modes/cfb/cfb_getiv.c create mode 100644 core/lib/libtomcrypt/src/modes/cfb/cfb_setiv.c create mode 100644 core/lib/libtomcrypt/src/modes/cfb/cfb_start.c create mode 100644 core/lib/libtomcrypt/src/modes/cfb/sub.mk create mode 100644 core/lib/libtomcrypt/src/modes/ctr/ctr_decrypt.c create mode 100644 core/lib/libtomcrypt/src/modes/ctr/ctr_done.c create mode 100644 core/lib/libtomcrypt/src/modes/ctr/ctr_encrypt.c create mode 100644 core/lib/libtomcrypt/src/modes/ctr/ctr_getiv.c create mode 100644 core/lib/libtomcrypt/src/modes/ctr/ctr_setiv.c create mode 100644 core/lib/libtomcrypt/src/modes/ctr/ctr_start.c create mode 100644 core/lib/libtomcrypt/src/modes/ctr/ctr_test.c create mode 100644 core/lib/libtomcrypt/src/modes/ctr/sub.mk create mode 100644 core/lib/libtomcrypt/src/modes/ecb/ecb_decrypt.c create mode 100644 core/lib/libtomcrypt/src/modes/ecb/ecb_done.c create mode 100644 core/lib/libtomcrypt/src/modes/ecb/ecb_encrypt.c create mode 100644 core/lib/libtomcrypt/src/modes/ecb/ecb_start.c create mode 100644 core/lib/libtomcrypt/src/modes/ecb/sub.mk create mode 100644 core/lib/libtomcrypt/src/modes/f8/f8_decrypt.c create mode 100644 core/lib/libtomcrypt/src/modes/f8/f8_done.c create mode 100644 core/lib/libtomcrypt/src/modes/f8/f8_encrypt.c create mode 100644 core/lib/libtomcrypt/src/modes/f8/f8_getiv.c create mode 100644 core/lib/libtomcrypt/src/modes/f8/f8_setiv.c create mode 100644 core/lib/libtomcrypt/src/modes/f8/f8_start.c create mode 100644 core/lib/libtomcrypt/src/modes/f8/f8_test_mode.c create mode 100644 core/lib/libtomcrypt/src/modes/f8/sub.mk create mode 100644 core/lib/libtomcrypt/src/modes/lrw/lrw_decrypt.c create mode 100644 core/lib/libtomcrypt/src/modes/lrw/lrw_done.c create mode 100644 core/lib/libtomcrypt/src/modes/lrw/lrw_encrypt.c create mode 100644 core/lib/libtomcrypt/src/modes/lrw/lrw_getiv.c create mode 100644 core/lib/libtomcrypt/src/modes/lrw/lrw_process.c create mode 100644 core/lib/libtomcrypt/src/modes/lrw/lrw_setiv.c create mode 100644 core/lib/libtomcrypt/src/modes/lrw/lrw_start.c create mode 100644 core/lib/libtomcrypt/src/modes/lrw/lrw_test.c create mode 100644 core/lib/libtomcrypt/src/modes/lrw/sub.mk create mode 100644 core/lib/libtomcrypt/src/modes/ofb/ofb_decrypt.c create mode 100644 core/lib/libtomcrypt/src/modes/ofb/ofb_done.c create mode 100644 core/lib/libtomcrypt/src/modes/ofb/ofb_encrypt.c create mode 100644 core/lib/libtomcrypt/src/modes/ofb/ofb_getiv.c create mode 100644 core/lib/libtomcrypt/src/modes/ofb/ofb_setiv.c create mode 100644 core/lib/libtomcrypt/src/modes/ofb/ofb_start.c create mode 100644 core/lib/libtomcrypt/src/modes/ofb/sub.mk create mode 100644 core/lib/libtomcrypt/src/modes/sub.mk create mode 100644 core/lib/libtomcrypt/src/modes/xts/sub.mk create mode 100644 core/lib/libtomcrypt/src/modes/xts/xts_decrypt.c create mode 100644 core/lib/libtomcrypt/src/modes/xts/xts_done.c create mode 100644 core/lib/libtomcrypt/src/modes/xts/xts_encrypt.c create mode 100644 core/lib/libtomcrypt/src/modes/xts/xts_init.c create mode 100644 core/lib/libtomcrypt/src/modes/xts/xts_mult_x.c create mode 100644 core/lib/libtomcrypt/src/modes/xts/xts_test.c create mode 100644 core/lib/libtomcrypt/src/mpa_desc.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/bit/sub.mk create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/boolean/sub.mk create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/choice/sub.mk create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/ia5/sub.mk create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/integer/sub.mk create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/sub.mk create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/octet/sub.mk create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/printable_string/sub.mk create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/sequence/sub.mk create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/set/sub.mk create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/short_integer/sub.mk create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/sub.mk create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/utctime/sub.mk create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c create mode 100644 core/lib/libtomcrypt/src/pk/asn1/der/utf8/sub.mk create mode 100644 core/lib/libtomcrypt/src/pk/asn1/sub.mk create mode 100644 core/lib/libtomcrypt/src/pk/dh/dh.c create mode 100644 core/lib/libtomcrypt/src/pk/dh/sub.mk create mode 100644 core/lib/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c create mode 100644 core/lib/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c create mode 100644 core/lib/libtomcrypt/src/pk/dsa/dsa_export.c create mode 100644 core/lib/libtomcrypt/src/pk/dsa/dsa_free.c create mode 100644 core/lib/libtomcrypt/src/pk/dsa/dsa_import.c create mode 100644 core/lib/libtomcrypt/src/pk/dsa/dsa_make_key.c create mode 100644 core/lib/libtomcrypt/src/pk/dsa/dsa_shared_secret.c create mode 100644 core/lib/libtomcrypt/src/pk/dsa/dsa_sign_hash.c create mode 100644 core/lib/libtomcrypt/src/pk/dsa/dsa_verify_hash.c create mode 100644 core/lib/libtomcrypt/src/pk/dsa/dsa_verify_key.c create mode 100644 core/lib/libtomcrypt/src/pk/dsa/sub.mk create mode 100644 core/lib/libtomcrypt/src/pk/ecc/ecc.c create mode 100644 core/lib/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c create mode 100644 core/lib/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c create mode 100644 core/lib/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c create mode 100644 core/lib/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c create mode 100644 core/lib/libtomcrypt/src/pk/ecc/ecc_export.c create mode 100644 core/lib/libtomcrypt/src/pk/ecc/ecc_free.c create mode 100644 core/lib/libtomcrypt/src/pk/ecc/ecc_get_size.c create mode 100644 core/lib/libtomcrypt/src/pk/ecc/ecc_import.c create mode 100644 core/lib/libtomcrypt/src/pk/ecc/ecc_make_key.c create mode 100644 core/lib/libtomcrypt/src/pk/ecc/ecc_shared_secret.c create mode 100644 core/lib/libtomcrypt/src/pk/ecc/ecc_sign_hash.c create mode 100644 core/lib/libtomcrypt/src/pk/ecc/ecc_sizes.c create mode 100644 core/lib/libtomcrypt/src/pk/ecc/ecc_test.c create mode 100644 core/lib/libtomcrypt/src/pk/ecc/ecc_verify_hash.c create mode 100644 core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_is_valid_idx.c create mode 100644 core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_map.c create mode 100644 core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c create mode 100644 core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c create mode 100644 core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c create mode 100644 core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_points.c create mode 100644 core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c create mode 100644 core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c create mode 100644 core/lib/libtomcrypt/src/pk/ecc/sub.mk create mode 100644 core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c create mode 100644 core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c create mode 100644 core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c create mode 100644 core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c create mode 100644 core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c create mode 100644 core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c create mode 100644 core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c create mode 100644 core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c create mode 100644 core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c create mode 100644 core/lib/libtomcrypt/src/pk/pkcs1/sub.mk create mode 100644 core/lib/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c create mode 100644 core/lib/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c create mode 100644 core/lib/libtomcrypt/src/pk/rsa/rsa_export.c create mode 100644 core/lib/libtomcrypt/src/pk/rsa/rsa_exptmod.c create mode 100644 core/lib/libtomcrypt/src/pk/rsa/rsa_free.c create mode 100644 core/lib/libtomcrypt/src/pk/rsa/rsa_import.c create mode 100644 core/lib/libtomcrypt/src/pk/rsa/rsa_make_key.c create mode 100644 core/lib/libtomcrypt/src/pk/rsa/rsa_sign_hash.c create mode 100644 core/lib/libtomcrypt/src/pk/rsa/rsa_verify_hash.c create mode 100644 core/lib/libtomcrypt/src/pk/rsa/sub.mk create mode 100644 core/lib/libtomcrypt/src/pk/sub.mk create mode 100644 core/lib/libtomcrypt/src/prngs/rng_get_bytes.c create mode 100644 core/lib/libtomcrypt/src/prngs/rng_make_prng.c create mode 100644 core/lib/libtomcrypt/src/prngs/sprng.c create mode 100644 core/lib/libtomcrypt/src/prngs/sub.mk create mode 100644 core/lib/libtomcrypt/src/prngs/yarrow.c create mode 100644 core/lib/libtomcrypt/src/sub.mk create mode 100644 core/lib/libtomcrypt/src/tee_ltc_wrapper.c create mode 100644 core/lib/libtomcrypt/sub.mk create mode 100644 core/lib/libtomcrypt/test/base64_test.c create mode 100644 core/lib/libtomcrypt/test/cipher_hash_test.c create mode 100644 core/lib/libtomcrypt/test/der_tests.c create mode 100644 core/lib/libtomcrypt/test/dsa_test.c create mode 100644 core/lib/libtomcrypt/test/ecc_test.c create mode 100644 core/lib/libtomcrypt/test/mac_test.c create mode 100644 core/lib/libtomcrypt/test/modes_test.c create mode 100644 core/lib/libtomcrypt/test/pkcs_1_test.c create mode 100644 core/lib/libtomcrypt/test/rsa_test.c create mode 100644 core/lib/libtomcrypt/test/store_test.c create mode 100644 core/lib/libtomcrypt/test/test.c create mode 100644 core/lib/libtomcrypt/test/test_driver.c create mode 100644 core/lib/libtomcrypt/test/tomcrypt_test.h create mode 100644 core/lib/libtomcrypt/test/unit_test.c create mode 100644 core/lib/libtomcrypt/test/x86_prof.c create mode 100644 core/mm/sub.mk create mode 100644 core/sub.mk create mode 100644 core/tee/sub.mk create mode 100644 core/tee/tee_acipher.c create mode 100644 core/tee/tee_authenc.c create mode 100644 core/tee/tee_cipher.c create mode 100644 core/tee/tee_fs.c create mode 100644 core/tee/tee_hash.c create mode 100644 core/tee/tee_mac.c create mode 100644 core/tee/tee_obj.c create mode 100644 core/tee/tee_pobj.c create mode 100644 core/tee/tee_rpmb.c create mode 100644 core/tee/tee_rpmb_fs.c create mode 100644 core/tee/tee_svc.c create mode 100644 core/tee/tee_svc_cryp.c create mode 100644 core/tee/tee_svc_storage.c create mode 100644 core/tee/tee_time_generic.c create mode 100644 documentation/build_system.md create mode 100644 documentation/file_structure.md create mode 100644 lib/libmpa/arch/arm32/sub.mk create mode 100644 lib/libmpa/include/mpa.h create mode 100644 lib/libmpa/include/mpa_assert.h create mode 100644 lib/libmpa/include/mpa_debug.h create mode 100644 lib/libmpa/include/mpalib.h create mode 100644 lib/libmpa/include/mpalib_config.h create mode 100644 lib/libmpa/mpa_addsub.c create mode 100644 lib/libmpa/mpa_arm_asm.s create mode 100644 lib/libmpa/mpa_cmp.c create mode 100644 lib/libmpa/mpa_conv.c create mode 100644 lib/libmpa/mpa_debug.c create mode 100644 lib/libmpa/mpa_div.c create mode 100644 lib/libmpa/mpa_expmod.c create mode 100644 lib/libmpa/mpa_gcd.c create mode 100644 lib/libmpa/mpa_init.c create mode 100644 lib/libmpa/mpa_io.c create mode 100644 lib/libmpa/mpa_mem_static.c create mode 100644 lib/libmpa/mpa_misc.c create mode 100644 lib/libmpa/mpa_modulus.c create mode 100644 lib/libmpa/mpa_montgomery.c create mode 100644 lib/libmpa/mpa_mul.c create mode 100644 lib/libmpa/mpa_primetable.h create mode 100644 lib/libmpa/mpa_primetest.c create mode 100644 lib/libmpa/mpa_random.c create mode 100644 lib/libmpa/mpa_shift.c create mode 100644 lib/libmpa/sub.mk create mode 100644 lib/libutee/abort.c create mode 100644 lib/libutee/arch/arm32/bget.c create mode 100644 lib/libutee/arch/arm32/bget.doc create mode 100644 lib/libutee/arch/arm32/bget.h create mode 100644 lib/libutee/arch/arm32/bget_malloc.c create mode 100644 lib/libutee/arch/arm32/bget_malloc.h create mode 100644 lib/libutee/arch/arm32/sub.mk create mode 100644 lib/libutee/arch/arm32/user_ta_entry.c create mode 100644 lib/libutee/arch/arm32/utee_misc.c create mode 100644 lib/libutee/arch/arm32/utee_syscalls_asm.S create mode 100644 lib/libutee/assert.c create mode 100644 lib/libutee/base64.c create mode 100644 lib/libutee/base64.h create mode 100644 lib/libutee/errno.c create mode 100644 lib/libutee/include/tee_api.h create mode 100644 lib/libutee/include/tee_api_defines.h create mode 100644 lib/libutee/include/tee_api_types.h create mode 100644 lib/libutee/include/tee_arith_internal.h create mode 100644 lib/libutee/include/tee_internal_api.h create mode 100644 lib/libutee/include/tee_internal_api_extensions.h create mode 100644 lib/libutee/include/tee_syscall_numbers.h create mode 100644 lib/libutee/include/tee_ta_api.h create mode 100644 lib/libutee/include/tee_trace.h create mode 100644 lib/libutee/include/tee_uta_trace.h create mode 100644 lib/libutee/include/user_ta_header.h create mode 100644 lib/libutee/include/utee_defines.h create mode 100644 lib/libutee/include/utee_syscalls.h create mode 100644 lib/libutee/include/utee_types.h create mode 100644 lib/libutee/sub.mk create mode 100644 lib/libutee/ta_trace.c create mode 100644 lib/libutee/tee_api.c create mode 100644 lib/libutee/tee_api_arith.c create mode 100644 lib/libutee/tee_api_objects.c create mode 100644 lib/libutee/tee_api_operations.c create mode 100644 lib/libutee/tee_api_property.c create mode 100644 lib/libutee/tee_user_mem.c create mode 100644 lib/libutee/tee_user_mem.h create mode 100644 lib/libutee/utee_misc.h create mode 100644 lib/libutils/ext/include/string_ext.h create mode 100644 lib/libutils/ext/strlcat.c create mode 100644 lib/libutils/ext/strlcpy.c create mode 100644 lib/libutils/ext/sub.mk create mode 100644 lib/libutils/isoc/arch/arm32/aeabi_divmod.c create mode 100644 lib/libutils/isoc/arch/arm32/aeabi_divmod_asm.S create mode 100644 lib/libutils/isoc/arch/arm32/sub.mk create mode 100644 lib/libutils/isoc/dlmalloc.c create mode 100644 lib/libutils/isoc/dlmalloc.h create mode 100644 lib/libutils/isoc/include/assert.h create mode 100644 lib/libutils/isoc/include/ctype.h create mode 100644 lib/libutils/isoc/include/inttypes.h create mode 100644 lib/libutils/isoc/include/limits.h create mode 100644 lib/libutils/isoc/include/malloc.h create mode 100644 lib/libutils/isoc/include/memory.h create mode 100644 lib/libutils/isoc/include/signal.h create mode 100644 lib/libutils/isoc/include/stdint.h create mode 100644 lib/libutils/isoc/include/stdio.h create mode 100644 lib/libutils/isoc/include/stdlib.h create mode 100644 lib/libutils/isoc/include/string.h create mode 100644 lib/libutils/isoc/include/sys/cdefs.h create mode 100644 lib/libutils/isoc/include/sys/queue.h create mode 100644 lib/libutils/isoc/include/sys/types.h create mode 100644 lib/libutils/isoc/include/time.h create mode 100644 lib/libutils/isoc/include/unistd.h create mode 100644 lib/libutils/isoc/include/wchar.h create mode 100644 lib/libutils/isoc/malloc_wrapper.c create mode 100644 lib/libutils/isoc/newlib/_ansi.h create mode 100644 lib/libutils/isoc/newlib/memchr.c create mode 100644 lib/libutils/isoc/newlib/memcmp.c create mode 100644 lib/libutils/isoc/newlib/memcpy.c create mode 100644 lib/libutils/isoc/newlib/memmove.c create mode 100644 lib/libutils/isoc/newlib/memset.c create mode 100644 lib/libutils/isoc/newlib/strcmp.c create mode 100644 lib/libutils/isoc/newlib/strlen.c create mode 100644 lib/libutils/isoc/newlib/strnlen.c create mode 100644 lib/libutils/isoc/newlib/sub.mk create mode 100644 lib/libutils/isoc/qsort.c create mode 100644 lib/libutils/isoc/snprintf.c create mode 100644 lib/libutils/isoc/stack_check.c create mode 100644 lib/libutils/isoc/strdup.c create mode 100644 lib/libutils/isoc/strndup.c create mode 100644 lib/libutils/isoc/sub.mk create mode 100644 lib/libutils/sub.mk create mode 100644 mk/cleanvars.mk create mode 100644 mk/compile.mk create mode 100644 mk/config.mk create mode 100644 mk/gcc.mk create mode 100644 mk/lib.mk create mode 100644 mk/subdir.mk create mode 100755 scripts/fixdep create mode 100644 ta/arch/arm32/link.mk create mode 100644 ta/arch/arm32/user_ta_elf_arm.lds create mode 100644 ta/arch/arm32/user_ta_header.c create mode 100644 ta/mk/ta_dev_kit.mk create mode 100644 ta/ta.mk diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000..855c9f8ec83 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.swp +cscope.* +out +.cproject +.project diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000000..fe903ec064a --- /dev/null +++ b/LICENSE @@ -0,0 +1,27 @@ +Unless it has its own copyright/license embedded in its body, each source file +is subject to the following license terms: + +Copyright (c) 2014, STMicroelectronics International N.V. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/Makefile b/Makefile new file mode 100644 index 00000000000..6b3358a9aa0 --- /dev/null +++ b/Makefile @@ -0,0 +1,41 @@ +SHELL = /bin/bash + +.PHONY: all +all: + +# Make these default for now +ARCH ?= arm32 +PLATFORM ?= orly2 +O ?= out/$(ARCH)-plat-$(PLATFORM) + +arch_$(ARCH) := y + +cmd-fixdep := ./scripts/fixdep + +ifneq ($O,) +out-dir := $O/ +endif + +ifneq ($V,1) +q := @ +cmd-echo := true +else +q := +cmd-echo := echo +endif + +include core/core.mk + +include ta/ta.mk + +.PHONY: clean +clean: + @echo Cleaning + ${q}rm -f $(cleanfiles) + +.PHONY: cscope +cscope: + @echo Creating cscope database + ${q}rm -f cscope.* + ${q}find $(PWD) -name "*.[chSs]" > cscope.files + ${q}cscope -b -q -k diff --git a/Notice.md b/Notice.md new file mode 100755 index 00000000000..6293a23b83b --- /dev/null +++ b/Notice.md @@ -0,0 +1,35 @@ +OP-TEE +======= + +This is the repository of OP-TEE (Open Portable Trusted Execution Environment), the open-source TEE maintained by STMicroelectronics, with initial contributions from STMicroelectronics, Ericsson, the Linaro industry association. + +What OP-TEE is +------ + +OP-TEE is designed primarily to rely on the ARM TrustZone(R) technology as the underlying hardware isolation mechanism. However, it has been structured to be compatible with any isolation technology suitable for the TEE concept and goals, such as running as a virtual machine or on a dedicated CPU. + +The main design goals for OP-TEE are: +- Isolation - the TEE provides isolation from the Rich OS (typically, Linux/Android) and it protects the Trusted Applications (TAs) it executes from each other, using underlying HW support, +- Small footprint - the TEE should remain small enough so that the TEE core, including all the code and data required to provide isolation, can reside in a reasonable amount of on-chip memory, +- Portability - the TEE must be easily pluggable to different architectures and available HW, and it has to support various setups such as multiple TEEs or multiple client OSes. + +Repository structure +------ + +OP-TEE is composed of three gits: +- The optee-client git, containing the source code for the TEE client library in Linux. This component provides the TEE Client API as defined by the GlobalPlatform TEE standard. It is distributed under the BSD 2-clause open-source license. +- The optee_os git, containing the source code for the TEE OS itself. This component provides the TEE Internal APIs as defined by the GlobalPlatform TEE standard to the Trusted Applications that it executes. It is distributed under the BSD 2-clause open-source license. +- The optee_linuxdriver git, containing the source code for the TEE driver in Linux. This component implements a generic TEE driver, designed primarily for TEE implementations that rely on the ARM TrustZone(R)technology. It is distributed under the GPLv2 open-source license. Please note that re-distribution under other versions of the GPL license is not allowed. The rationale behind this limitation is to ensure that this code may be used on products which have security devices which prevent reloading the code. Such security devices would be incompatible with some licenses such as GPLv3 and so distribution under those licenses would be inconsistent with this goal. Therefore it is recommended that care be taken before redistributing any of the components under other license terms than those provided here. + +Contributions +------ + +Contributions to OP-TEE are managed by the OP-TEE gatekeepers, whose contact email is op-tee-support[at]st[.]com. + +Contributions must be original work of the contributor. In order to preserve the rights of the contributor while allowing distribution to and protection of the recipients of OP-TEE, the contributor must complete, sign and send the Contribution Agreement or a scanned copy to ST for counter-signature, prior to any contribution. The address where to send the agreement and other details will be provided upon contact with the OP-TEE gatekeepers. +Once the Contribution Agreement is complete, the contributor may propose contributions to the OP-TEE gatekeepers. Proposed Contributions are reviewed for acceptance by the OP-TEE gatekeepers and the OP-TEE community. + +Submission of non-original work +------ + +You may submit work that is not your original creation separately from any Contribution, identifying the complete details of its source and of any license or other restriction of which you are personally aware. Such submissions are not subject to the Contribution Agreement. They are reviewed for acceptance by the OP-TEE gatekeepers and the OP-TEE community. diff --git a/core/arch/arm32/include/arm32.h b/core/arch/arm32/include/arm32.h new file mode 100644 index 00000000000..2c5e963aa7f --- /dev/null +++ b/core/arch/arm32/include/arm32.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ARM32_H +#define ARM32_H + +#ifndef ASM +#include +#endif + +#define CPSR_MODE_MASK 0x1f +#define CPSR_MODE_USR 0x10 +#define CPSR_MODE_FIQ 0x11 +#define CPSR_MODE_IRQ 0x12 +#define CPSR_MODE_SVC 0x13 +#define CPSR_MODE_MON 0x16 +#define CPSR_MODE_ABT 0x17 +#define CPSR_MODE_UND 0x1b +#define CPSR_MODE_SYS 0x1f + +#define CPSR_T (1 << 5) +#define CPSR_F (1 << 6) +#define CPSR_I (1 << 7) + +#define MPIDR_CPU_MASK 0xff +#define MPIDR_CLUSTER_MASK (0xff << 8) + +#define SCR_NS (1 << 0) +#define SCR_IRQ (1 << 1) +#define SCR_FIQ (1 << 2) +#define SCR_EA (1 << 3) +#define SCR_FW (1 << 4) +#define SCR_AW (1 << 5) +#define SCR_NET (1 << 6) +#define SCR_SCD (1 << 7) +#define SCR_HCE (1 << 8) +#define SCR_SIF (1 << 9) + +#define SCTLR_M (1 << 0) +#define SCTLR_A (1 << 1) +#define SCTLR_C (1 << 2) +#define SCTLR_CP15BEN (1 << 5) +#define SCTLR_SW (1 << 10) +#define SCTLR_Z (1 << 11) +#define SCTLR_I (1 << 12) +#define SCTLR_V (1 << 13) +#define SCTLR_RR (1 << 14) +#define SCTLR_HA (1 << 17) +#define SCTLR_WXN (1 << 19) +#define SCTLR_UWXN (1 << 20) +#define SCTLR_FI (1 << 21) +#define SCTLR_VE (1 << 24) +#define SCTLR_EE (1 << 25) +#define SCTLR_NMFI (1 << 26) +#define SCTLR_TRE (1 << 28) +#define SCTLR_AFE (1 << 29) +#define SCTLR_TE (1 << 30) + +#ifndef ASM +static inline uint32_t read_mpidr(void) +{ + uint32_t mpidr; + + asm ("mrc p15, 0, %[mpidr], c0, c0, 5" + : [mpidr] "=r" (mpidr) + ); + + return mpidr; +} + +static inline uint32_t read_sctlr(void) +{ + uint32_t sctlr; + + asm ("mrc p15, 0, %[sctlr], c1, c0, 0" + : [sctlr] "=r" (sctlr) + ); + + return sctlr; +} + +static inline void write_sctlr(uint32_t sctlr) +{ + asm ("mcr p15, 0, %[sctlr], c1, c0, 0" + : : [sctlr] "r" (sctlr) + ); +} + +static inline void write_ttbr0(uint32_t ttbr0) +{ + asm ("mcr p15, 0, %[ttbr0], c2, c0, 0" + : : [ttbr0] "r" (ttbr0) + ); +} + +static inline void write_dacr(uint32_t dacr) +{ + asm ("mcr p15, 0, %[dacr], c3, c0, 0" + : : [dacr] "r" (dacr) + ); +} + +static inline void isb(void) +{ + asm ("isb"); +} + +static inline void dsb(void) +{ + asm ("dsb"); +} + +static inline void write_tlbiallis(void) +{ + /* Invalidate entire unified TLB Inner Shareable, r0 ignored */ + asm ("mcr p15, 0, r0, c8, c3, 0"); +} + +static inline uint32_t read_cpsr(void) +{ + uint32_t cpsr; + + asm ("mrs %[cpsr], cpsr" + : [cpsr] "=r" (cpsr) + ); + return cpsr; +} + +static inline void write_cpsr(uint32_t cpsr) +{ + asm ("msr cpsr, %[cpsr]" + : : [cpsr] "r" (cpsr) + ); +} +#endif + +#endif /*ARM32_H*/ diff --git a/core/arch/arm32/include/arm32_macros.S b/core/arch/arm32/include/arm32_macros.S new file mode 100644 index 00000000000..ae85a479a8b --- /dev/null +++ b/core/arch/arm32/include/arm32_macros.S @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + .macro read_sctlr reg + mrc p15, 0, \reg, c1, c0, 0 + .endm + + .macro write_sctlr reg + mcr p15, 0, \reg, c1, c0, 0 + .endm + + .macro read_scr reg + mrc p15, 0, \reg, c1, c1, 0 + .endm + + .macro write_scr reg + mcr p15, 0, \reg, c1, c1, 0 + .endm + + .macro read_mpidr reg + mrc p15, 0, \reg, c0, c0, 5 + .endm + + .macro write_vbar reg + mcr p15, 0, \reg, c12, c0, 0 + .endm + + .macro write_mvbar reg + mcr p15, 0, \reg, c12, c0, 1 + .endm diff --git a/core/arch/arm32/include/kernel/arch_debug.h b/core/arch/arm32/include/kernel/arch_debug.h new file mode 100644 index 00000000000..1774b202452 --- /dev/null +++ b/core/arch/arm32/include/kernel/arch_debug.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef KERNEL_ARCH_DEBUG_H +#define KERNEL_ARCH_DEBUG_H + +void check_canaries(void); + +#endif /*KERNEL_ARCH_DEBUG_H*/ diff --git a/core/arch/arm32/include/kernel/asc.h b/core/arch/arm32/include/kernel/asc.h new file mode 100644 index 00000000000..f942c6613ba --- /dev/null +++ b/core/arch/arm32/include/kernel/asc.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef ASC_H +#define ASC_H + +extern int asc_init(void); +extern int __asc_xmit_char(const char p); +extern int __asc_xmit(const char *s); +extern void __asc_flush(void); + +#endif diff --git a/core/arch/arm32/include/kernel/kta_types.h b/core/arch/arm32/include/kernel/kta_types.h new file mode 100644 index 00000000000..c308cfd8219 --- /dev/null +++ b/core/arch/arm32/include/kernel/kta_types.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * \file kta_types.h + * \brief This file contains types related to the secure library API. + * @{ + */ + +#ifndef KTA_TYPES_H +#define KTA_TYPES_H + +#include + +/* + * KTA return value type + */ + +/* Return code type */ +typedef uint32_t t_kta_return_value; + +/* + * Structure of return type + * ----------------------------------------------------------------- + * | flags | domain | code | + * ----------------------------------------------------------------- + * 31 28 27 16 15 0 + */ +/* flags: 0x0 = success / 0x8 = failure */ + +/* Success codes (domain = D, error code =Y) */ +/* #define KTA_RET_OK_REASON_X (0x000Y000X) */ +#define KTA_RET_OK ((t_kta_return_value)0x00000001) +#define KTA_RET_BUSY ((t_kta_return_value)0x00000003) + +/* Failure codes (domain = D, error code =Y) */ +/* #define KTA_RET_FAIL_ERROR_X (0x900Y000X) */ +#define KTA_RET_FAIL ((t_kta_return_value)0x90000001) +#define KTA_RET_NON_SUPPORTED_APPL ((t_kta_return_value)0x90000002) +#define KTA_RET_NON_VALID_ADDRESS ((t_kta_return_value)0x90000003) +#define KTA_RET_MMU_TRANSLATION_FAULT ((t_kta_return_value)0x90000004) +#define KTA_RET_INVALID_ARGS ((t_kta_return_value)0x90000005) + +typedef struct kta_signed_header { + uint32_t magic; + uint16_t size_of_signed_header; + uint16_t size_of_signature; + uint32_t sign_hash_type; /* see t_hash_type */ + uint32_t signature_type; /* see t_signature_type */ + uint32_t hash_type; /* see t_hash_type */ + uint32_t payload_type; /* see enum kta_payload_type */ + uint32_t flags; /* reserved */ + uint32_t size_of_payload; + uint32_t sw_vers_nbr; + uint32_t load_address; + uint32_t startup_address; + uint32_t spare; /* reserved */ +} kta_signed_header_t; + +#endif /* End of kta_types.h */ + +/** @} */ diff --git a/core/arch/arm32/include/kernel/misc.h b/core/arch/arm32/include/kernel/misc.h new file mode 100644 index 00000000000..f084eabe401 --- /dev/null +++ b/core/arch/arm32/include/kernel/misc.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef KERNEL_MISC_H +#define KERNEL_MISC_H + +#include + +size_t get_core_pos(void); + +#endif /*KERNEL_MISC_H*/ + diff --git a/core/arch/arm32/include/kernel/tee_l2cc_mutex.h b/core/arch/arm32/include/kernel/tee_l2cc_mutex.h new file mode 100644 index 00000000000..8cc99240ac3 --- /dev/null +++ b/core/arch/arm32/include/kernel/tee_l2cc_mutex.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +TEE_Result tee_l2cc_mutex_configure(uint32_t service_id, uint32_t *mutex); diff --git a/core/arch/arm32/include/kernel/tee_misc.h b/core/arch/arm32/include/kernel/tee_misc.h new file mode 100644 index 00000000000..00e91c6413f --- /dev/null +++ b/core/arch/arm32/include/kernel/tee_misc.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_MISC_H +#define TEE_MISC_H + +#include + +/* + * Macro to derive hex string buffer size from binary buffer size & the + * reverse + */ +#define TEE_B2HS_HSBUF_SIZE(x) ((x) * 2 + 1) +#define TEE_HS2B_BBUF_SIZE(x) ((x + 1) >> 1) + +/* + * binary to hex string buffer + * Returns the number of data bytes written to the hex string + */ +uint32_t tee_b2hs(uint8_t *b, uint8_t *hs, uint32_t blen, uint32_t hslen); + +/* + * hex string to binary buffer + * Returns the number of data bytes written to the bin buffer + */ +uint32_t tee_hs2b(uint8_t *hs, uint8_t *b, uint32_t hslen, uint32_t blen); + +#endif /* TEE_MISC_H */ diff --git a/core/arch/arm32/include/kernel/thread.h b/core/arch/arm32/include/kernel/thread.h new file mode 100644 index 00000000000..e4cb17dfb60 --- /dev/null +++ b/core/arch/arm32/include/kernel/thread.h @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef KERNEL_THREAD_H +#define KERNEL_THREAD_H + +#include + +#define THREAD_ID_0 0 +#define THREAD_ABT_STACK 0xfffffffe +#define THREAD_TMP_STACK 0xffffffff + +struct thread_smc_args { + uint32_t a0; + uint32_t a1; + uint32_t a2; + uint32_t a3; + uint32_t a4; /* Thread ID when returning from RPC */ + uint32_t a5; + uint32_t a6; /* Optional session ID */ + uint32_t a7; /* Hypervisor Client ID */ +}; + + +struct thread_abort_regs { + uint32_t spsr; + uint32_t pad; + uint32_t r0; + uint32_t r1; + uint32_t r2; + uint32_t r3; + uint32_t ip; + uint32_t lr; +}; +typedef void (*thread_abort_handler_t)(uint32_t abort_type, + struct thread_abort_regs *regs); +struct thread_svc_regs { + uint32_t r0; + uint32_t r1; + uint32_t r2; + uint32_t r3; + uint32_t r4; + uint32_t r5; + uint32_t lr; + uint32_t spsr; +}; +typedef void (*thread_svc_handler_t)(struct thread_svc_regs *regs); +typedef void (*thread_call_handler_t)(struct thread_smc_args *args); +typedef void (*thread_fiq_handler_t)(void); +struct thread_handlers { + /* + * stdcall and fastcall are called as regular functions and + * normal ARM Calling Convention applies. Return values are passed + * args->param{1-3} and forwarded into r0-r3 when returned to + * non-secure world. + * + * stdcall handles calls which can be preemted from non-secure + * world. This handler is executed with a large stack. + * + * fastcall handles fast calls which can't be preemted. This + * handler is executed with a limited stack. This handler must not + * cause any aborts or reenenable FIQs which are temporarily masked + * while executing this handler. + * + * TODO execute fastcalls and FIQs on different stacks allowing + * FIQs to be enabled during a fastcall. + */ + thread_call_handler_t stdcall; + thread_call_handler_t fastcall; + + /* + * fiq is called as a regular function and normal ARM Calling + * Convention applies. + * + * This handler handles FIQs which can't be preemted. This handler + * is executed with a limited stack. This handler must not cause + * any aborts or reenenable FIQs which are temporarily masked while + * executing this handler. + */ + thread_fiq_handler_t fiq; + + /* + * The SVC handler is called as a normal function and should do + * a normal return. Note that IRQ is masked when this function + * is called, it's permitted for the function to unmask IRQ. + */ + thread_svc_handler_t svc; + + /* + * The abort handler is called as a normal function and should do + * a normal return. The abort handler is called when an undefined, + * prefetch abort, or data abort exception is received. In all + * cases the abort handler is executing in abort mode. If IRQ is + * unmasked in the abort handler it has to have separate abort + * stacks for each thread. + */ + thread_abort_handler_t abort; +}; +void thread_init_handlers(const struct thread_handlers *handlers); + +/* + * Sets the stacks to be used by the different threads. Use THREAD_ID_0 for + * first stack, THREAD_ID_0 + 1 for the next and so on. + * + * If stack_id == THREAD_ID_TMP_STACK the temporary stack used by current + * CPU is selected. + * If stack_id == THREAD_ID_ABT_STACK the abort stack used by current CPU + * is selected. + * + * Returns true on success and false on errors. + */ +bool thread_init_stack(uint32_t stack_id, vaddr_t sp); + +/* + * Set Thread Specific Data (TSD) pointer together a function + * to free the TSD on thread_exit. + */ +typedef void (*thread_tsd_free_t)(void *tsd); +void thread_set_tsd(void *tsd, thread_tsd_free_t free_func); + +/* Returns Thread Specific Data (TSD) pointer. */ +void *thread_get_tsd(void); + +/* + * Sets IRQ status for current thread, must only be called from an + * active thread context. + * + * enable == true -> enable IRQ + * enable == false -> disable IRQ + */ +void thread_set_irq(bool enable); + +/* + * Restores the IRQ status (in CPSR) for current thread, must only be called + * from an active thread context. + */ +void thread_restore_irq(void); + +/** + * Allocates data for struct teesmc32_arg. + * + * @size: size in bytes of struct teesmc32_arg + * + * @returns 0 on failure or a physical pointer to a struct teesmc32_arg buffer + * on success. + */ +paddr_t thread_rpc_alloc_arg(size_t size); + +/** + * Allocates data for a payload buffer. + * + * @size: size in bytes of payload buffer + * + * @returns 0 on failure or a physical pointer to a payload buffer on success. + */ +paddr_t thread_rpc_alloc_payload(size_t size); + +/** + * Free physical memory previously allocated with thread_rpc_alloc_arg() + * + * @arg: physical pointer to struct teesmc32_arg buffer + */ +void thread_rpc_free_arg(paddr_t arg); + +/** + * Free physical memory previously allocated with thread_rpc_alloc_payload() + * + * @arg: physical pointer to struct teesmc32_arg buffer + */ +void thread_rpc_free_payload(paddr_t payload); + +/** + * Does an RPC with a physical pointer to a struct teesmc32_arg + * + * @arg: physical pointer to struct teesmc32_arg + */ +void thread_rpc_cmd(paddr_t arg); + +/** + * Extension: Allocates data for payload buffers. + * + * @size: size in bytes of payload buffer + * @payload: returned physcial pointer to payload buffer + * @cookie: returned cookie used when freeing the buffer + */ +void thread_st_rpc_alloc_payload(size_t size, paddr_t *payload, + paddr_t *cookie); + +/** + * Extension: Free physical memory previously allocated with thread_rpc_alloc() + * + * @cookie: cookie received when allocating the payload buffer + */ +void thread_st_rpc_free_payload(paddr_t cookie); + +#endif /*KERNEL_THREAD_H*/ diff --git a/core/arch/arm32/include/kernel/thread_defs.h b/core/arch/arm32/include/kernel/thread_defs.h new file mode 100644 index 00000000000..b3b984704a0 --- /dev/null +++ b/core/arch/arm32/include/kernel/thread_defs.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef KERNEL_THREAD_DEFS_H +#define KERNEL_THREAD_DEFS_H + +#define THREAD_FLAGS_COPY_ARGS_ON_RETURN (1 << 0) +#define THREAD_FLAGS_IRQ_ENABLE (1 << 1) + +#define THREAD_ABORT_UNDEF 0 +#define THREAD_ABORT_PREFETCH 1 +#define THREAD_ABORT_DATA 2 + +#endif /*KERNEL_THREAD_DEFS_H*/ diff --git a/core/arch/arm32/include/kernel/tz_proc.h b/core/arch/arm32/include/kernel/tz_proc.h new file mode 100644 index 00000000000..95eb58261fb --- /dev/null +++ b/core/arch/arm32/include/kernel/tz_proc.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TZ_PROC_H +#define TZ_PROC_H + +void cpu_dsb(void); +void cpu_dmb(void); +void cpu_isb(void); +void cpu_wfe(void); +void cpu_sev(void); + +void cpu_disable_its(void); +void cpu_enable_its(void); +unsigned int cpu_read_cpsr(void); +void cpu_write_cpsr(unsigned int cpsr); + +unsigned int cpu_read_ttbr0(void); +void cpu_write_ttbr0(unsigned int ttbr0); + +void cpu_spin_lock(unsigned int *lock); +unsigned int cpu_spin_trylock(unsigned int *lock); +void cpu_spin_unlock(unsigned int *lock); + +void mmu_enable(void); +void mmu_enable_icache(void); +void mmu_enable_dcache(void); + +#endif diff --git a/core/arch/arm32/include/kernel/tz_proc_def.h b/core/arch/arm32/include/kernel/tz_proc_def.h new file mode 100644 index 00000000000..2b3ec8def9c --- /dev/null +++ b/core/arch/arm32/include/kernel/tz_proc_def.h @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* ***************************************************************************** + * * * + * * Description: This file contains constant assembly definitions for Orly2 * + * * configuration * + * ***************************************************************************** + */ + +/* + * General constants + */ + +/* + * CP15 Multiprocessor Affinity register (MPIDR) + */ +#define CP15_CONFIG_CPU_ID_MASK 0x00000003 +#define CPU_ID0 0x00000000 +#define CPU_ID1 0x00000001 + +/* + * CP15 Secure configuration register + */ +#define CP15_CONFIG_NS_MASK 0x00000001 +#define CP15_CONFIG_IRQ_MASK 0x00000002 +#define CP15_CONFIG_FIQ_MASK 0x00000004 +#define CP15_CONFIG_EA_MASK 0x00000008 +#define CP15_CONFIG_FW_MASK 0x00000010 +#define CP15_CONFIG_AW_MASK 0x00000020 +#define CP15_CONFIG_nET_MASK 0x00000040 + +/* + * CP15 Control register + */ +#define CP15_CONTROL_M_MASK 0x00000001 +#define CP15_CONTROL_C_MASK 0x00000004 +#define CP15_CONTROL_Z_MASK 0x00000800 +#define CP15_CONTROL_I_MASK 0x00001000 +#define CP15_CONTROL_V_MASK 0x00002000 +#define CP15_CONTROL_HA_MASK 0x00020000 +#define CP15_CONTROL_EE_MASK 0x02000000 +#define CP15_CONTROL_NMFI_MASK 0x08000000 +#define CP15_CONTROL_TRE_MASK 0x10000000 +#define CP15_CONTROL_AFE_MASK 0x20000000 +#define CP15_CONTROL_TE_MASK 0x40000000 + +/* + * CP15 Auxiliary Control register + */ +#define CP15_CONTROL_SMP_MASK 0x00000040 +#define CP15_CONTROL_EXCL_MASK 0x00000080 + +/* + * CP15 Non secure access control register + */ +#define CP15_NSAC_TL_MASK 0x10000 +#define CP15_NSAC_CL_MASK 0x20000 +#define CP15_NSAC_CPN_MASK 0x3FFF + +/* + * CP15 Cache register + */ +#define CP15_CACHE_ADDR_R_BIT 12 +#define CP15_CACHE_ADDR_L_BIT (32-CP15_CACHE_ADDR_R_BIT) +#define CP15_CACHE_RESULT_MASK 0x00000001 + +/* + * CP15 TCM register + * + * ITCM configuration (4kbytes, @0x20100000, enabled) + * DTCM configuration (4kbytes, @0x20101000, enabled) + */ +#define CP15_TCM_ENABLE_MASK 0x00000001 +#define CP15_TCM_INSTR_TCM 0x2010000C +#define CP15_TCM_DATA_TCM 0x2010100C + +/* + * CP15 cache lockdown register + * + * ITCM configuration (4kbytes, @0x20100000, enabled) + * DTCM configuration (4kbytes, @0x20101000, enabled) + */ +#define CP15_CACHE_LOCK_ALLWAYS_MASK 0x0000000F + +/* + * CP15 cache cleaning constant definition + */ +/* start of line number field offset in way/index format */ +#define LINE_FIELD_OFFSET 5 +/* Warning: this assumes a 256 lines/way cache (32kB cache) */ +#define LINE_FIELD_OVERFLOW 13 +/* start of way number field offset in way/index format */ +#define WAY_FIELD_OFFSET 30 + +/* + * CPSR definitions + */ + + /* Values */ +#define CPSR_USER_MODE 0x10 /* 10000b */ +#define CPSR_FIQ_MODE 0x11 /* 10001b */ +#define CPSR_IRQ_MODE 0x12 /* 10010b */ +#define CPSR_SVC_MODE 0x13 /* 10011b */ +#define CPSR_MON_MODE 0x16 /* 10110b */ +#define CPSR_ABORT_MODE 0x17 /* 10111b */ +#define CPSR_UNDEF_MODE 0x1B /* 11011b */ +#define CPSR_SYSTEM_MODE 0x1F /* 11111b */ +#define CPSR_CLR_MASK_MODE 0x1F /* 11111b */ + + /* Masks */ +#define CPSR_ARM_THUMB_MODE_MASK 0x020 /* 100000b ARM = 0, THUMB = 1 */ +#define CPSR_FIQ_IRQ_MASK 0x0C0 /* 11000000b */ +#define CPSR_FIQ_MASK 0x040 /* 01000000b */ +#define CPSR_IRQ_MASK 0x080 /* 10000000b */ +#define CPSR_A_MASK 0x100 /* 100000000b */ +#define CPSR_INST_MODE_FIQ_IRQ_MASK 0x0E0 /* 11100000b */ + + /* Bits */ +#define CPSR_FIQ_BIT 0x6 +#define CPSR_IRQ_BIT 0x7 + +/* + * SCU related definitions + */ +#define SCU_INV_ALL_WAYS_CPU0 0xF +#define SCU_INV_ALL_WAYS_CPU1 0xF0 +#define SCU_ENABLE_MASK 1 +#define SCU_FILTERING_ENABLE_MASK 2 +#define END_FILTERING_SCU_ADDR 0x3FFFFFFF + +/* Stack OFFSET definition */ +#define TWO_REGS_OFFSET 0x08 +#define THREE_REGS_OFFSET 0x0C +#define FOUR_REGS_OFFSET 0x10 +#define SIX_REGS_OFFSET 0x18 +#define SEVEN_REGS_OFFSET 0x1C +#define EIGHT_REGS_OFFSET 0x20 +#define TEN_REGS_OFFSET 0x28 +#define LOCK_INIT 2 +#define LOCK 1 +#define UNLOCK 0 +#define ARM_STORE_DONE 0 +#define ARM_STORE_FAILED 1 diff --git a/core/arch/arm32/include/kernel/tz_ssvce.h b/core/arch/arm32/include/kernel/tz_ssvce.h new file mode 100644 index 00000000000..81127fbaaa0 --- /dev/null +++ b/core/arch/arm32/include/kernel/tz_ssvce.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TZ_SSVCE_H +#define TZ_SSVCE_H + +unsigned int secure_get_cpu_id(void); + +void arm_cl1_d_cleanbysetway(void); +void arm_cl1_d_invbysetway(void); +void arm_cl1_d_cleaninvbysetway(void); +void arm_cl1_d_cleanbypa(unsigned long start, unsigned long end); +void arm_cl1_d_invbypa(unsigned long start, unsigned long end); +void arm_cl1_d_cleaninvbypa(unsigned long start, unsigned long end); + +void arm_cl1_i_inv_all(void); +void arm_cl1_i_inv(unsigned long start, unsigned long end); + +void arm_cl2_cleaninvbyway(void); +void arm_cl2_invbyway(void); +void arm_cl2_cleanbyway(void); +void arm_cl2_cleanbypa(unsigned long start, unsigned long end); +void arm_cl2_invbypa(unsigned long start, unsigned long end); +void arm_cl2_cleaninvbypa(unsigned long start, unsigned long end); + +void secure_mmu_datatlbinvall(void); +void secure_mmu_unifiedtlbinvall(void); +void secure_mmu_unifiedtlbinvbymva(unsigned long addr); +void secure_mmu_unifiedtlbinv_curasid(void); +void secure_mmu_unifiedtlbinv_byasid(unsigned long asid); + +void secure_mmu_disable(void); + +#endif diff --git a/core/arch/arm32/include/kernel/tz_ssvce_def.h b/core/arch/arm32/include/kernel/tz_ssvce_def.h new file mode 100644 index 00000000000..99f4e766f54 --- /dev/null +++ b/core/arch/arm32/include/kernel/tz_ssvce_def.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * ARMv7 Secure Services library + */ + +#define CPSR_OFFSET 0x00 +#define STACK_INT_USAGE 0x04 + +/* + * tee service IDs (TODO: align with the service ID list). + * Set by NSec in R4 before SMC to request a TEE service. + */ +#define SSAPI_RET_FROM_INT_SERV 4 +#define SSAPI_RET_FROM_RPC_SERV 5 + +/* + * TEE monitor: status returned by the routine that checks the entry + * reason (valid Service ID / secure context). + */ +#define SEC_INVALID_ENTRY 0 +#define SEC_PRE_INIT_ENTRY 1 +#define SEC_RET_FROM_INT_ENTRY 2 +#define SEC_RET_FROM_RPC_ENTRY 3 +#define SEC_NORMAL_ENTRY 4 + +/* + * teecore exit reason. + * Set by Secure in R4 before SMC to request a switch to NSec. + */ +#define SEC_EXIT_NORMAL 1 +#define SEC_EXIT_START_EXT_CODE 2 +#define SEC_EXIT_INT 3 +#define SEC_EXIT_RPC_CALL 4 +#define SEC_EXIT_FIRST 5 +#define SEC_EXIT_DEEP_SLEEP 6 + +/* misc */ + +#define SEC_UNDEF_STACK_OFFSET 4 +#define SEC_ABORT_STACK_OFFSET 12 + +#define SEC_ENTRY_STATUS_NOK 0 +#define SEC_ENTRY_STATUS_OK 1 diff --git a/core/arch/arm32/include/mm/core_memprot.h b/core/arch/arm32/include/mm/core_memprot.h new file mode 100644 index 00000000000..1a04c6db8ab --- /dev/null +++ b/core/arch/arm32/include/mm/core_memprot.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef CORE_MEMPROT_H +#define CORE_MEMPROT_H + +#include +#include + +/* + * "pbuf_is" support. + * + * core_vbuf_is()/core_pbuf_is() can be used to check if a teecore mapped + * virtual address or a physical address is "Secure", "Unsecure", "external + * RAM" and some other fancy attributes. + * + * DO NOT use 'buf_is(Secure, buffer)==false' as a assumption that buffer is + * UnSecured ! This is NOT a valid asumption ! A buffer is certified UnSecured + * only if 'buf_is(UnSecure, buffer)==true'. + */ + +/* memory atttributes */ +enum buf_is_attr { + CORE_MEM_SEC, + CORE_MEM_NON_SEC, + CORE_MEM_TEE_RAM, + CORE_MEM_TA_RAM, + CORE_MEM_NSEC_SHM, + CORE_MEM_MULTPURPOSE, + CORE_MEM_EXTRAM, + CORE_MEM_INTRAM, + CORE_MEM_CACHED, +}; + +/* redirect legacy tee_vbuf_is() and tee_pbuf_is() to our routines */ +#define tee_pbuf_is core_pbuf_is +#define tee_vbuf_is core_vbuf_is + +/* Convenience macros */ +#define tee_pbuf_is_non_sec(buf, len) \ + core_pbuf_is(CORE_MEM_NON_SEC, (tee_paddr_t)(buf), (len)) + +#define tee_pbuf_is_sec(buf, len) \ + core_pbuf_is(CORE_MEM_SEC, (tee_paddr_t)(buf), (len)) + +#define tee_vbuf_is_non_sec(buf, len) \ + core_vbuf_is(CORE_MEM_NON_SEC, (void *)(buf), (len)) + +#define tee_vbuf_is_sec(buf, len) \ + core_vbuf_is(CORE_MEM_SEC, (void *)(buf), (len)) + +/* See kta_mem.h for flags to tee_pbuf_is() and tee_kbuf_is() */ + +/* + * This function return true if the buf complies with supplied flags. + * If this function returns false buf doesn't comply with supplied flags + * or something went wrong. + * + * Note that returning false doesn't guarantee that buf complies with + * the complement of the supplied flags. + */ +bool core_pbuf_is(uint32_t flags, tee_paddr_t pbuf, size_t len); + +/* + * Translates the supplied virtual address to a physical address and uses + * tee_phys_buf_is() to check the compliance of the buffer. + */ +bool core_vbuf_is(uint32_t flags, const void *vbuf, size_t len); + +#endif /* CORE_MEMPROT_H */ diff --git a/core/arch/arm32/include/mm/core_mmu.h b/core/arch/arm32/include/mm/core_mmu.h new file mode 100644 index 00000000000..26bd60af226 --- /dev/null +++ b/core/arch/arm32/include/mm/core_mmu.h @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef CORE_MMU_H +#define CORE_MMU_H + +#include +#include +#include + +/* + * @type: enumerate: specifiy the purpose of the memory area. + * @pa: memory area physical start address + * @size: memory area size in bytes + * @va: virtual start address (0 if memory is not mapped) + * @region_size: size of the mapping region used (4k, 64K, 1MB) + * @secure: true if memory area in inside a A9 secure area + */ +struct map_area { + unsigned int type; + unsigned int pa; + size_t size; + /* below here are core_mmu.c internal data */ + unsigned int va; + unsigned int region_size; + bool secure; + bool cached; + bool device; + bool rw; + bool exec; +}; + +/* + * Memory area type: + * MEM_AREA_NOTYPE: Undefined type. Used as end of table. + * MEM_AREA_TEE_RAM: teecore execution RAM (secure, reserved to TEEtz, unused) + * MEM_AREA_TEE_COHERENT: teecore coherent RAM (secure, reserved to TEEtz) + * MEM_AREA_TA_RAM: Secure RAM where teecore loads/exec TA instances. + * MEM_AREA_NS_SHM: NonSecure shared RAM between NSec and TEEtz. + * MEM_AREA_KEYVAULT: Secure RAM storing some secrets + * MEM_AREA_IO_SEC: Secure HW mapped registers + * MEM_AREA_IO_NSEC: NonSecure HW mapped registers + * MEM_AREA_MAXTYPE: lower invalid 'type' value + */ +enum teecore_memtypes { + MEM_AREA_NOTYPE = 0, + MEM_AREA_TEE_RAM, + MEM_AREA_TEE_COHERENT, + MEM_AREA_TA_RAM, + MEM_AREA_NSEC_SHM, + MEM_AREA_KEYVAULT, + MEM_AREA_IO_SEC, + MEM_AREA_IO_NSEC, + MEM_AREA_MAXTYPE +}; + +/* Default NSec shared memory allocated from NSec world */ +extern unsigned long default_nsec_shm_paddr; +extern unsigned long default_nsec_shm_size; + +uint32_t core_map_area_flag(void *p, size_t l); +unsigned int core_init_mmu(unsigned int core_ttbr0, unsigned int ta_ttbr0); + +int core_mmu_map(unsigned long paddr, size_t size, unsigned long flags); +int core_mmu_unmap(unsigned long paddr, size_t size); + +void core_mmu_get_mem_by_type(unsigned int type, unsigned int *s, + unsigned int *e); + +int core_va2pa(uint32_t va, uint32_t *pa); +int core_pa2va(uint32_t pa, uint32_t *va); + +/* get phys base addr of MMU L1 table used for tee core */ +uint32_t core_mmu_get_ttbr0_base(void); +uint32_t core_mmu_get_ttbr0_attr(void); +uint32_t core_mmu_get_ttbr0(void); + +/* get virt and phys base addr of MMU L1 table used for TAs */ +uint32_t core_mmu_get_ta_ul1_va(void); +uint32_t core_mmu_get_ta_ul1_pa(void); + +/* routines to retreive shared mem configuration */ +bool core_mmu_is_shm_cached(void); + +/* L1/L2 cache maintenance (op: refer to ???) */ +unsigned int core_cache_maintenance(int op, void *start, size_t len); +void core_l2cc_mutex_set(void *mutex); +void core_l2cc_mutex_activate(bool en); + +/* various invalidate secure TLB */ +enum teecore_tlb_op { + TLBINV_DATATLB, /* invalidate data tlb */ + TLBINV_UNIFIEDTLB, /* invalidate unified tlb */ + TLBINV_CURRENT_ASID, /* invalidate unified tlb for current ASID */ + TLBINV_BY_ASID, /* invalidate unified tlb by ASID */ + TLBINV_BY_MVA, /* invalidate unified tlb by MVA */ +}; + +struct map_area *bootcfg_get_memory(void); +int core_tlb_maintenance(int op, unsigned int a); +unsigned long bootcfg_get_pbuf_is_handler(void); + +/* Cache maintenance operation type */ +typedef enum { + DCACHE_CLEAN = 0x1, + DCACHE_AREA_CLEAN = 0x2, + DCACHE_INVALIDATE = 0x3, + DCACHE_AREA_INVALIDATE = 0x4, + ICACHE_INVALIDATE = 0x5, + ICACHE_AREA_INVALIDATE = 0x6, + WRITE_BUFFER_DRAIN = 0x7, + DCACHE_CLEAN_INV = 0x8, + DCACHE_AREA_CLEAN_INV = 0x9, + L2CACHE_INVALIDATE = 0xA, + L2CACHE_AREA_INVALIDATE = 0xB, + L2CACHE_CLEAN = 0xC, + L2CACHE_AREA_CLEAN = 0xD, + L2CACHE_CLEAN_INV = 0xE, + L2CACHE_AREA_CLEAN_INV = 0xF +} t_cache_operation_id; + +#endif /* CORE_MMU_H */ diff --git a/core/arch/arm32/include/mm/tee_mm_def.h b/core/arch/arm32/include/mm/tee_mm_def.h new file mode 100644 index 00000000000..1647364896c --- /dev/null +++ b/core/arch/arm32/include/mm/tee_mm_def.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TEE_MM_DEF_H +#define TEE_MM_DEF_H + +#define SMALL_PAGE_SHIFT 12 +#define SMALL_PAGE_MASK 0xfff +#define SMALL_PAGE_SIZE 0x1000 + +#define SECTION_SHIFT 20 +#define SECTION_MASK 0x000fffff +#define SECTION_SIZE 0x00100000 + +#define TEE_VMEM_START 0x40000000 +#define TEE_VMEM_SIZE (1024 * 1024) + +/* virtual addresses of ROM code variables and L2 MMU tables */ +#define SEC_VIRT_MMU_L2_BASE 0x40000000 + +/* Paged virtual memory defines */ +#define TEE_PVMEM_PSIZE (TEE_VMEM_SIZE / SMALL_PAGE_SIZE) + +#define TEE_PVMEM_LO TEE_VMEM_START + +/* define section to load */ +#define TEE_DDR_VLOFFSET 0x1 + +/* Reset error code */ +#define TEE_RESET_INVALID_PAGE_ERROR 0xBADB7000 + +/* + * MMU related values + */ +#define TEE_VIRT_MMU_L2_BASE TEE_VMEM_START +#define TEE_VIRT_MMU_L2_SIZE 0x400 +#define TEE_MMU_UL1_BASE core_mmu_get_ta_ul1_va() +#define TEE_MMU_UL1_PA_BASE core_mmu_get_ta_ul1_pa() + +#define TEE_MMU_DEFAULT_ATTRS \ + (TEE_MMU_TTB_S | TEE_MMU_TTB_IRGN_WBWA | TEE_MMU_TTB_RNG_WBWA) + +/* Page attributes */ + +/* + * Small pages [31:12]PA, not Global, Sharable, Access Permission, + * Memory region attribute [8:6], Access permissions [5:4], + * C, B, Small page, Outer and Inner Write-Back, Write-Allocate + */ +#define TEE_PAGER_PAGE_UNLOADED \ + (TEE_MMU_L2SP_SMALL_PAGE | TEE_MMU_L2SP_WBWA | TEE_MMU_L2SP_S) + +#define TEE_PAGER_PAGE_LOADED \ + (TEE_PAGER_PAGE_UNLOADED | TEE_MMU_L2SP_PRIV_ACC) + +#define TEE_PAGER_STACKS_ATTRIBUTES \ + (TEE_PAGER_PAGE_LOADED | TEE_MMU_L2SP_XN) + +#define TEE_PAGER_NO_ACCESS_ATTRIBUTES 0x00000000 + +#define TEE_ROM_AREA_START TEE_VMEM_START +#define TEE_ROM_AREA_SIZE 0x2000 + +#define TEE_HOLE_START (TEE_ROM_AREA_START + TEE_ROM_AREA_SIZE) +#define TEE_HOLE_SIZE 0x2000 + +/* Has to be kept in sync with elf_arm.x */ +#define TEE_STACK_AREA_START (TEE_HOLE_START + TEE_HOLE_SIZE) +/* Stack is not physically contigious. */ +#define TEE_STACK_AREA_START0 TEE_STACK_AREA_START +#define TEE_STACK_AREA_SIZE0 0x3000 +#define TEE_STACK_AREA_SIZE TEE_STACK_AREA_SIZE0 + +/* Has to be kept in sync with elf_arm.x */ +#define TEE_CODE_START (TEE_STACK_AREA_START + TEE_STACK_AREA_SIZE) +#define TEE_CODE_SIZE 0xA000 + +#define TEE_HEAP_START (TEE_CODE_START + TEE_CODE_SIZE) +/* + * This address has to be 16kb aligned as the first few bytes are + * used to hold the L1 mmu descriptor for user mode mapping. + */ +#define TEE_HEAP_START0 TEE_HEAP_START + + +/* + * Register addresses related to time + * RTT = Real-Time Timer + * RTT0 = Real-Time Timer 0 + * RTT1 = Real-Time Timer 1 + */ +#define RTT_CR_EN 0x2 +#define RTT_CR_ENS 0x4 +#define RTT_IMSC_IMSC 0x1 +#define RTT_MIS_MIS 0x1 + +/* RTT0 definition */ +#define RTT0_REG_START_ADDR 0x80152000 +#define RTT0_CTCR (RTT0_REG_START_ADDR) +#define RTT0_IMSC (RTT0_REG_START_ADDR + 0x04) +#define RTT0_RIS (RTT0_REG_START_ADDR + 0x08) +#define RTT0_MIS (RTT0_REG_START_ADDR + 0x0C) +#define RTT0_ICR (RTT0_REG_START_ADDR + 0x10) +#define RTT0_DR (RTT0_REG_START_ADDR + 0x14) +#define RTT0_LR (RTT0_REG_START_ADDR + 0x18) +#define RTT0_CR (RTT0_REG_START_ADDR + 0x1c) + +/* RTT1 definition */ +#define RTT1_REG_START_ADDR 0x80153000 +#define RTT1_CTCR (RTT1_REG_START_ADDR) +#define RTT1_IMSC (RTT1_REG_START_ADDR + 0x04) +#define RTT1_RIS (RTT1_REG_START_ADDR + 0x08) +#define RTT1_MIS (RTT1_REG_START_ADDR + 0x0C) +#define RTT1_ICR (RTT1_REG_START_ADDR + 0x10) +#define RTT1_DR (RTT1_REG_START_ADDR + 0x14) +#define RTT1_LR (RTT1_REG_START_ADDR + 0x18) +#define RTT1_CR (RTT1_REG_START_ADDR + 0x1c) + +#endif diff --git a/core/arch/arm32/include/mm/tee_mmu_defs.h b/core/arch/arm32/include/mm/tee_mmu_defs.h new file mode 100644 index 00000000000..82241d26c04 --- /dev/null +++ b/core/arch/arm32/include/mm/tee_mmu_defs.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_MMU_DEFS_H +#define TEE_MMU_DEFS_H + +/* Number of sections in ttbr0 */ +#define TEE_MMU_UL1_NUM_ENTRIES 32 +#define TEE_MMU_UL1_NUM_USER_ENTRIES (TEE_MMU_UL1_NUM_ENTRIES / 2) +#define TEE_MMU_UL1_NUM_KERN_ENTRIES (TEE_MMU_UL1_NUM_ENTRIES - \ + TEE_MMU_UL1_NUM_USER_ENTRIES) + +#define TEE_MMU_UL1_SIZE (TEE_MMU_UL1_NUM_ENTRIES * sizeof(uint32_t)) +#define TEE_MMU_UL1_USER_SIZE (TEE_MMU_UL1_NUM_USER_ENTRIES * sizeof(uint32_t)) +#define TEE_MMU_UL1_KERN_SIZE (TEE_MMU_UL1_NUM_KERN_ENTRIES * sizeof(uint32_t)) + +#define TEE_MMU_UL1_KERN_BASE (TEE_MMU_UL1_BASE + TEE_MMU_UL1_USER_SIZE) + +/* TTB attributes */ + +/* Mask for all attributes */ +/* #define TEE_MMU_TTB_ATTR_MASK ((1 << 7) - 1) */ + +/* Sharable */ +#define TEE_MMU_TTB_S (1 << 1) + +/* Not Outer Sharable */ +#define TEE_MMU_TTB_NOS (1 << 5) + +/* Normal memory, Inner Non-cacheable */ +#define TEE_MMU_TTB_IRGN_NC 0 + +/* Normal memory, Inner Write-Back Write-Allocate Cacheable */ +#define TEE_MMU_TTB_IRGN_WBWA (1 << 6) + +/* Normal memory, Inner Write-Through Cacheable */ +#define TEE_MMU_TTB_IRGN_WT 1 + +/* Normal memory, Inner Write-Back no Write-Allocate Cacheable */ +#define TEE_MMU_TTB_IRGN_WB (1 | (1 << 6)) + +/* Normal memory, Outer Write-Back Write-Allocate Cacheable */ +#define TEE_MMU_TTB_RNG_WBWA (1 << 3) + +#define TEE_MMU_TTBRX_TTBX_MASK (((1 << 18) - 1) << 14) +#define TEE_MMU_TTBRX_ATTR_MASK ((1 << 14) - 1) + +/* + * Second-level descriptor Small page table Attributes + */ + +/* Small page */ +#define TEE_MMU_L2SP_SMALL_PAGE (1 << 1) + +/* Execute never */ +#define TEE_MMU_L2SP_XN 1 + +/* Normal memory, Outer Write-Back Write-Allocate Cacheable */ +#define TEE_MMU_L2SP_WBWA ((1 << 6) | (1 << 3) | (1 << 2)) + +/* Not global */ +#define TEE_MMU_L2SP_NG (1 << 11) + +/* Sharable */ +#define TEE_MMU_L2SP_S (1 << 10) + +/* Privileged access only */ +#define TEE_MMU_L2SP_PRIV_ACC (1 << 4) + +/* Clear access from attribute */ +#define TEE_MMU_L2SP_CLEAR_ACC(attr) ((attr) & ~((1 << 5) | (1 << 4))) + +#endif /* TEE_MMU_DEFS_H */ diff --git a/core/arch/arm32/include/mm/tee_pager_defines.h b/core/arch/arm32/include/mm/tee_pager_defines.h new file mode 100644 index 00000000000..30cd3181f58 --- /dev/null +++ b/core/arch/arm32/include/mm/tee_pager_defines.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_PAGER_DEFINES_H +#define TEE_PAGER_DEFINES_H + +#define TEE_PAGER_NORMAL_RETURN 0 +#define TEE_PAGER_USER_TA_PANIC 1 + +#define TEE_PAGER_SPSR_MODE_MASK 0x1F +#define TEE_PAGER_SPSR_MODE_USR 0x10 +#define TEE_PAGER_SPSR_MODE_SVC 0x13 +#define TEE_PAGER_SPSR_MODE_ABT 0x17 +#define TEE_PAGER_SPSR_MODE_MON 0x16 + +#define TEE_PAGER_DATA_ABORT 0x00000000 +#define TEE_PAGER_PREF_ABORT 0x00000001 +#define TEE_PAGER_UNDEF_ABORT 0x00000002 + +#endif /* TEE_PAGER_DEFINES_H */ diff --git a/core/arch/arm32/include/mm/tee_pager_unpg.h b/core/arch/arm32/include/mm/tee_pager_unpg.h new file mode 100644 index 00000000000..b91b684509b --- /dev/null +++ b/core/arch/arm32/include/mm/tee_pager_unpg.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This h-file holds shared internal defintions for tee_pager*.[cs] + * and should not be included in other files. + */ + +#ifndef TEE_PAGER_UNPG_H +#define TEE_PAGER_UNPG_H + +#include +#include +#include +#include + +/* Interesting aborts for TEE pager */ +#define TEE_FSR_FS_MASK 0x040F +#define TEE_FSR_FS_ALIGNMENT_FAULT 0x0001 /* DFSR[10,3:0] 0b00001 */ +#define TEE_FSR_FS_DEBUG_EVENT 0x0002 /* DFSR[10,3:0] 0b00010 */ +#define TEE_FSR_FS_ASYNC_EXTERNAL_ABORT 0x0406 /* DFSR[10,3:0] 0b10110 */ +#define TEE_FSR_FS_PERMISSION_FAULT_SECTION 0x000D /* DFSR[10,3:0] 0b01101 */ +#define TEE_FSR_FS_PERMISSION_FAULT_PAGE 0x000F /* DFSR[10,3:0] 0b01111 */ + +/* + * Represents a physical page used for paging. + * + * mmu_entry points to currently used MMU entry. This actual physical + * address is stored here so even if the page isn't mapped, there's allways + * an MMU entry holding the physical address. + * + * session_handle is a pointer returned by tee_ta_load_page() and later + * used when saving rw-data. + */ +struct tee_pager_pmem { + uint32_t *mmu_entry; + void *ctx_handle; + TAILQ_ENTRY(tee_pager_pmem) link; +}; + +TAILQ_HEAD(tee_pager_pmem_head, tee_pager_pmem); + +/* Head of registered physical pages */ +extern struct tee_pager_pmem_head tee_pager_pmem_head; +/* Number of registered physical pages, used hiding pages. */ +extern uint8_t tee_pager_npages; + +void tee_pager_abort_handler(uint32_t abort_type, + struct thread_abort_regs *regs); + +/* Returns the IFAR register */ +uint32_t TEE_PAGER_GET_IFAR_asm(void); +/* Returns the DFAR register */ +uint32_t TEE_PAGER_GET_DFAR_asm(void); +/* Returns the DFSR register */ +uint32_t TEE_PAGER_GET_DFSR_asm(void); +uint32_t TEE_PAGER_GET_CPUID_asm(void); +/* Returns the IFSR register */ +uint32_t TEE_PAGER_GET_IFSR_asm(void); +/* Returns the SPSR register */ +uint32_t tee_pager_get_spsr(void); + +/* Called for each core to setup core for tee pager. */ +extern void TEE_PAGER_INIT_asm(void); + +/* Get VA from L2 MMU entry address */ +#define TEE_PAGER_GET_VA(a) \ + (((((uint32_t)a) - SEC_VIRT_MMU_L2_BASE) << \ + (SMALL_PAGE_SHIFT - 2)) + TEE_VMEM_START) + +/* Get L2 MMU entry address from virtual address */ +static inline uint32_t *tee_pager_get_mmu_entry(tee_vaddr_t va) +{ + tee_vaddr_t addr = va & ~SMALL_PAGE_MASK; + size_t mmu_entry_offset = (addr - TEE_VMEM_START) >> SMALL_PAGE_SHIFT; + + return (uint32_t *)(TEE_VIRT_MMU_L2_BASE + + mmu_entry_offset * sizeof(uint32_t)); +} + +/* Returns true if the exception originated from user mode */ +bool tee_pager_is_user_exception(void); +/* Returns true if the exception originated from abort mode */ +bool tee_pager_is_abort_in_abort_handler(void); + +void tee_pager_restore_irq(void); + +#endif /* TEE_PAGER_UNPG_H */ diff --git a/core/arch/arm32/include/sm/sm.h b/core/arch/arm32/include/sm/sm.h new file mode 100644 index 00000000000..a0327d83058 --- /dev/null +++ b/core/arch/arm32/include/sm/sm.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SM_SM_H +#define SM_SM_H + +#include + +struct sm_nsec_ctx { + uint32_t usr_sp; + uint32_t usr_lr; + uint32_t irq_spsr; + uint32_t irq_sp; + uint32_t irq_lr; + uint32_t svc_spsr; + uint32_t svc_sp; + uint32_t svc_lr; + uint32_t abt_spsr; + uint32_t abt_sp; + uint32_t abt_lr; + uint32_t und_spsr; + uint32_t und_sp; + uint32_t und_lr; + uint32_t mon_lr; + uint32_t mon_spsr; + uint32_t r4; + uint32_t r5; + uint32_t r6; + uint32_t r7; + uint32_t r8; + uint32_t r9; + uint32_t r10; + uint32_t r11; + uint32_t r12; +}; + +struct sm_sec_ctx { + uint32_t usr_sp; + uint32_t usr_lr; + uint32_t irq_spsr; + uint32_t irq_sp; + uint32_t irq_lr; + uint32_t svc_spsr; + uint32_t svc_sp; + uint32_t svc_lr; + uint32_t abt_spsr; + uint32_t abt_sp; + uint32_t abt_lr; + uint32_t und_spsr; + uint32_t und_sp; + uint32_t und_lr; + uint32_t mon_lr; + uint32_t mon_spsr; +}; + +/* Returns storage location of non-secure context for current CPU */ +struct sm_nsec_ctx *sm_get_nsec_ctx(void); + +/* Returns storage location of secure context for current CPU */ +struct sm_sec_ctx *sm_get_sec_ctx(void); + +/* Returns stack pointer to use in monitor mode for current CPU */ +void *sm_get_sp(void); + + +/* + * Initializes secure monitor, must be called by each CPU + */ +void sm_init(vaddr_t stack_pointer); + +#endif /*SM_SM_H*/ diff --git a/core/arch/arm32/include/sm/sm_defs.h b/core/arch/arm32/include/sm/sm_defs.h new file mode 100644 index 00000000000..eae324300e3 --- /dev/null +++ b/core/arch/arm32/include/sm/sm_defs.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SM_SM_DEFS_H +#define SM_SM_DEFS_H + +/* + * sm_smc_entry uses 6 * 4 bytes + * sm_fiq_entry uses 6 * 4 bytes + * + * Add some spare space since a couple of C functions are called using this + * stack. These functions can sometimes use more stack depending on + * compiler options. + */ +#define SM_STACK_SIZE (12 * 4) + +#endif /*SM_SM_DEFS_H*/ diff --git a/core/arch/arm32/include/sm/tee_mon.h b/core/arch/arm32/include/sm/tee_mon.h new file mode 100644 index 00000000000..9e546d64f9a --- /dev/null +++ b/core/arch/arm32/include/sm/tee_mon.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_MON_H +#define TEE_MON_H + +#include +#include +#include +#include "tee_api_types.h" +#include "user_ta_header.h" + +extern ta_static_head_t __start_ta_head_section; +extern ta_static_head_t __stop_ta_head_section; +extern TEE_Result init_teecore(void); + +/* teecore heap address/size is defined in scatter file */ +extern unsigned char teecore_heap_start; +extern unsigned char teecore_heap_end; + +#endif /* TEE_MON_H */ diff --git a/core/arch/arm32/include/sm/teesmc.h b/core/arch/arm32/include/sm/teesmc.h new file mode 100644 index 00000000000..11ba4f94ae9 --- /dev/null +++ b/core/arch/arm32/include/sm/teesmc.h @@ -0,0 +1,716 @@ +/* + * Copyright (c) 2014, Linaro Limited + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEESMC_H +#define TEESMC_H + +#ifndef ASM +/* + * This section depends on uint64_t, uint32_t uint8_t already being + * defined. Since this file is used in several different environments + * (secure world OS and normal world Linux kernel to start with) where + * stdint.h may not be available it's the responsibility of the one + * including this file to provide those types. + */ + +/* + * Trusted OS SMC interface. + * + * The SMC interface follows SMC Calling Convention + * (ARM_DEN0028A_SMC_Calling_Convention). + * + * The primary objective of this API is to provide a transport layer on + * which a Global Platform compliant TEE interfaces can be deployed. But the + * interface can also be used for other implementations. + * + * This file is divided in two parts. + * Part 1 deals with passing parameters to Trusted Applications running in + * a trusted OS in secure world. + * Part 2 deals with the lower level handling of the SMC. + */ + +/* + ******************************************************************************* + * Part 1 - passing parameters to Trusted Applications + ******************************************************************************* + */ + +/* + * Same values as TEE_PARAM_* from TEE Internal API + */ +#define TEESMC_ATTR_TYPE_NONE 0 +#define TEESMC_ATTR_TYPE_VALUE_INPUT 1 +#define TEESMC_ATTR_TYPE_VALUE_OUTPUT 2 +#define TEESMC_ATTR_TYPE_VALUE_INOUT 3 +#define TEESMC_ATTR_TYPE_MEMREF_INPUT 5 +#define TEESMC_ATTR_TYPE_MEMREF_OUTPUT 6 +#define TEESMC_ATTR_TYPE_MEMREF_INOUT 7 + +#define TEESMC_ATTR_TYPE_MASK 0x7 + +/* + * Meta parameter to be absorbed by the Secure OS and not passed + * to the Trusted Application. + * + * One example of this is a struct teesmc_meta_open_session which + * is added to TEESMC{32,64}_CMD_OPEN_SESSION. + */ +#define TEESMC_ATTR_META 0x8 + +/* + * Used as an indication from normal world of compatible cache usage. + * 'I' stands for inner cache and 'O' for outer cache. + */ +#define TEESMC_ATTR_CACHE_I_NONCACHE 0x0 +#define TEESMC_ATTR_CACHE_I_WRITE_THR 0x1 +#define TEESMC_ATTR_CACHE_I_WRITE_BACK 0x2 +#define TEESMC_ATTR_CACHE_O_NONCACHE 0x0 +#define TEESMC_ATTR_CACHE_O_WRITE_THR 0x4 +#define TEESMC_ATTR_CACHE_O_WRITE_BACK 0x8 + +#define TEESMC_ATTR_CACHE_DEFAULT (TEESMC_ATTR_CACHE_I_WRITE_BACK | \ + TEESMC_ATTR_CACHE_O_WRITE_BACK) + +#define TEESMC_ATTR_CACHE_SHIFT 4 +#define TEESMC_ATTR_CACHE_MASK 0xf + +#define TEESMC_CMD_OPEN_SESSION 0 +#define TEESMC_CMD_INVOKE_COMMAND 1 +#define TEESMC_CMD_CLOSE_SESSION 2 +#define TEESMC_CMD_CANCEL 3 + +/** + * struct teesmc32_param_memref - memory reference + * @buf_ptr: Address of the buffer + * @size: Size of the buffer + * + * Secure and normal world communicates pointer via physical address instead of + * the virtual address with is usually used for pointers. This is because + * Secure and normal world has completely independant memory mapping. Normal + * world can even have a hypervisor which need to translate the guest + * physical address (AKA IPA in ARM lingo) to a real physical address + * before passing the structure to secure world. + */ +struct teesmc32_param_memref { + uint32_t buf_ptr; + uint32_t size; +}; + +/** + * struct teesmc32_param_memref - memory reference + * @buf_ptr: Address of the buffer + * @size: Size of the buffer + * + * See description of struct teesmc32_param_memref. + */ +struct teesmc64_param_memref { + uint64_t buf_ptr; + uint64_t size; +}; + +/** + * struct teesmc32_param_value - values + * @a: first value + * @b: second value + */ +struct teesmc32_param_value { + uint32_t a; + uint32_t b; +}; + +/** + * struct teesmc64_param_value - values + * @a: first value + * @b: second value + */ +struct teesmc64_param_value { + uint64_t a; + uint64_t b; +}; + +/** + * struct teesmc32_param - parameter + * @attr: attributes + * @memref: a memory reference + * @value: a value + * + * attr & TEESMC_ATTR_TYPE_MASK indicates if memref or value is used in the + * union. TEESMC_ATTR_TYPE_VALUE_* indicates value and + * TEESMC_ATTR_TYPE_MEMREF_* indicates memref. TEESMC_ATTR_TYPE_NONE + * indicates that none of the members are used. + */ +struct teesmc32_param { + uint32_t attr; + union { + struct teesmc32_param_memref memref; + struct teesmc32_param_value value; + } u; +}; + +/** + * struct teesmc64_param - parameter + * @attr: attributes + * @memref: a memory reference + * @value: a value + * + * See description of union teesmc32_param. + */ +struct teesmc64_param { + uint64_t attr; + union { + struct teesmc64_param_memref memref; + struct teesmc64_param_value value; + } u; +}; + +/** + * struct teesmc32_arg - SMC argument for Trusted OS + * @cmd: Command, one of TEESMC_CMD_* + * @ta_func: Trusted Application function, specific to the Trusted Application, + * used if cmd == TEESMC_CMD_INVOKE_COMMAND + * @session: In parameter for all TEESMC_CMD_* except + * TEESMC_CMD_OPEN_SESSION where it's an output paramter instead + * @ret: return value + * @ret_origin: origin of the return value + * @num_params: number of parameters supplied to the OS Command + * @params: the parameters supplied to the OS Command + * + * All normal SMC calls to Trusted OS uses this struct. If cmd requires + * further information than what these field holds it can be passed as a + * parameter tagged as meta (setting the TEESMC_ATTR_META bit in + * corresponding param_attrs). This is used for TEESMC_CMD_OPEN_SESSION + * to pass a struct teesmc32_meta_open_session which is needed find the + * Trusted Application and to indicate the credentials of the client. + */ +struct teesmc32_arg { + uint32_t cmd; + uint32_t ta_func; + uint32_t session; + uint32_t ret; + uint32_t ret_origin; + uint32_t num_params; +#if 0 + /* + * Commented out elements used to visualize the layout dynamic part + * of the struct. Note that these fields are not available at all + * if num_params == 0. + * + * params is accessed through the macro TEESMC32_GET_PARAMS + */ + + struct teesmc32_param params[num_params]; +#endif +}; + +/** + * TEESMC32_GET_PARAMS - return pointer to union teesmc32_param * + * + * @x: Pointer to a struct teesmc32_arg + * + * Returns a pointer to the params[] inside a struct teesmc32_arg. + */ +#define TEESMC32_GET_PARAMS(x) \ + (struct teesmc32_param *)(((struct teesmc32_arg *)(x)) + 1) + +/** + * TEESMC32_GET_ARG_SIZE - return size of struct teesmc32_arg + * + * @num_params: Number of parameters embedded in the struct teesmc32_arg + * + * Returns the size of the struct teesmc32_arg together with the number + * of embedded paramters. + */ +#define TEESMC32_GET_ARG_SIZE(num_params) \ + (sizeof(struct teesmc32_arg) + \ + sizeof(struct teesmc32_param) * (num_params)) + +/** + * struct teesmc64_arg - SMC argument for Trusted OS + * @cmd: OS Command, one of TEESMC_CMD_* + * @ta_func: Trusted Application function, specific to the Trusted Application + * @session: In parameter for all TEESMC_CMD_* but + * TEESMC_CMD_OPEN_SESSION + * @ret: return value + * @ret_origin: origin of the return value + * @num_params: number of parameters supplied to the OS Command + * @params: the parameters supplied to the OS Command + * + * See description of struct teesmc32_arg. + */ +struct teesmc64_arg { + uint64_t cmd; + uint64_t ta_func; + uint64_t session; + uint64_t ret; + uint64_t ret_origin; + uint64_t num_params; +#if 0 + /* + * Commented out elements used to visualize the layout dynamic part + * of the struct. Note that these fields are not available at all + * if num_params == 0. + * + * params is accessed through the macro TEESMC64_GET_PARAMS + */ + + union teesmc64_param params[num_params]; +#endif +}; + +/** + * TEESMC64_GET_PARAMS - return pointer to union teesmc64_param * + * + * @x: Pointer to a struct teesmc64_arg + * + * Returns a pointer to the params[] inside a struct teesmc64_arg. + */ +#define TEESMC64_GET_PARAMS(x) \ + (struct teesmc64_param *)(((struct teesmc64_arg *)(x)) + 1) + +/** + * TEESMC64_GET_ARG_SIZE - return size of struct teesmc64_arg + * + * @num_params: Number of parameters embedded in the struct teesmc64_arg + * + * Returns the size of the struct teesmc64_arg together with the number + * of embedded paramters. + */ +#define TEESMC64_GET_ARG_SIZE(num_params) \ + (sizeof(struct teesmc64_arg) + \ + sizeof(union teesmc64_param) * (num_params)) + +#define TEESMC_UUID_LEN 16 + +/** + * struct teesmc_meta_open_session - additional parameters for + * TEESMC32_CMD_OPEN_SESSION and + * TEESMC64_CMD_OPEN_SESSION + * @uuid: UUID of the Trusted Application + * @clnt_uuid: UUID of client + * @clnt_login: Login class of client, TEE_LOGIN_* if being Global Platform + * compliant + * + * This struct is passed in the first parameter as an input memref tagged + * as meta on an TEESMC{32,64}_CMD_OPEN_SESSION cmd. It's important + * that it really is the first parameter to make it easy for an eventual + * hypervisor to inspect and possibly update clnt_* values. + */ +struct teesmc_meta_open_session { + uint8_t uuid[TEESMC_UUID_LEN]; + uint8_t clnt_uuid[TEESMC_UUID_LEN]; + uint32_t clnt_login; +}; + + +#endif /*!ASM*/ + +/* + ******************************************************************************* + * Part 2 - low level SMC interaction + ******************************************************************************* + */ + +#define TEESMC_32 0 +#define TEESMC_64 0x40000000 +#define TEESMC_FAST_CALL 0x80000000 +#define TEESMC_STD_CALL 0 + +#define TEESMC_OWNER_MASK 0x3F +#define TEESMC_OWNER_SHIFT 24 + +#define TEESMC_FUNC_MASK 0xFFFF + +#define TEESMC_IS_FAST_CALL(smc_val) ((smc_val) & TEESMC_FAST_CALL) +#define TEESMC_IS_64(smc_val) ((smc_val) & TEESMC_64) +#define TEESMC_FUNC_NUM(smc_val) ((smc_val) & TEESMC_FUNC_MASK) +#define TEESMC_OWNER_NUM(smc_val) (((smc_val) >> TEESMC_OWNER_SHIFT) & \ + TEESMC_OWNER_MASK) + +#define TEESMC_CALL_VAL(type, calling_convention, owner, func_num) \ + ((type) | (calling_convention) | \ + (((owner) & TEESMC_OWNER_MASK) << TEESMC_OWNER_SHIFT) |\ + ((func_num) & TEESMC_FUNC_MASK)) + +#define TEESMC_OWNER_ARCH 0 +#define TEESMC_OWNER_CPU 1 +#define TEESMC_OWNER_SIP 2 +#define TEESMC_OWNER_OEM 3 +#define TEESMC_OWNER_STANDARD 4 +#define TEESMC_OWNER_TRUSTED_APP 48 +#define TEESMC_OWNER_TRUSTED_OS 50 + +#define TEESMC_OWNER_TRUSTED_OS_API 63 + +/* + * Function specified by SMC Calling convention. + */ +#define TEESMC32_FUNCID_CALLS_COUNT 0xFF00 +#define TEESMC32_CALLS_COUNT \ + TEESMC_CALL_VAL(TEESMC_32, TEESMC_FAST_CALL, \ + TEESMC_OWNER_TRUSTED_OS_API, \ + TEESMC32_FUNCID_CALLS_COUNT) + +/* + * Function specified by SMC Calling convention + * + * Return one of the following UIDs if using API specified in this file + * without further extentions: + * 65cb6b93-af0c-4617-8ed6-644a8d1140f8 : Only 32 bit calls are supported + * 65cb6b93-af0c-4617-8ed6-644a8d1140f9 : Both 32 and 64 bit calls are supported + */ +#define TEESMC_UID_R0 0x65cb6b93 +#define TEESMC_UID_R1 0xaf0c4617 +#define TEESMC_UID_R2 0x8ed6644a +#define TEESMC_UID32_R3 0x8d1140f8 +#define TEESMC_UID64_R3 0x8d1140f9 +#define TEESMC32_FUNCID_CALLS_UID 0xFF01 +#define TEESMC32_CALLS_UID \ + TEESMC_CALL_VAL(TEESMC_32, TEESMC_FAST_CALL, \ + TEESMC_OWNER_TRUSTED_OS_API, \ + TEESMC32_FUNCID_CALLS_UID) + +/* + * Function specified by SMC Calling convention + * + * Returns 1.0 if using API specified in this file without further extentions. + */ +#define TEESMC_REVISION_MAJOR 1 +#define TEESMC_REVISION_MINOR 0 +#define TEESMC32_FUNCID_CALLS_REVISION 0xFF03 +#define TEESMC32_CALLS_REVISION \ + TEESMC_CALL_VAL(TEESMC_32, TEESMC_FAST_CALL, \ + TEESMC_OWNER_TRUSTED_OS_API, \ + TEESMC32_FUNCID_CALLS_REVISION) + +/* + * Get UUID of Trusted OS. + * + * Used by non-secure world to figure out which Trusted OS is installed. + * Note that returned UUID is the UUID of the Trusted OS, not of the API. + * + * Returns UUID in r0-4/w0-4 in the same way as TEESMC32_CALLS_UID + * described above. + */ +#define TEESMC_FUNCID_GET_OS_UUID 0 +#define TEESMC32_CALL_GET_OS_UUID \ + TEESMC_CALL_VAL(TEESMC_32, TEESMC_FAST_CALL, TEESMC_OWNER_TRUSTED_OS, \ + TEESMC_FUNCID_GET_OS_UUID) + +/* + * Get revision of Trusted OS. + * + * Used by non-secure world to figure out which version of the Trusted OS + * is installed. Note that the returned revision is the revision of the + * Trusted OS, not of the API. + * + * Returns revision in r0-1/w0-1 in the same way as TEESMC32_CALLS_REVISION + * described above. + */ +#define TEESMC_FUNCID_GET_OS_REVISION 1 +#define TEESMC32_CALL_GET_OS_REVISION \ + TEESMC_CALL_VAL(TEESMC_32, TEESMC_FAST_CALL, TEESMC_OWNER_TRUSTED_OS, \ + TEESMC_FUNCID_GET_OS_REVISION) + + + +/* + * Call with struct teesmc32_arg as argument + * + * Call register usage: + * r0/x0 SMC Function ID, TEESMC32_CALL_WITH_ARG + * r1/x1 Physical pointer to a struct teesmc32_arg + * r2-6/x2-6 Not used + * r7/x7 Hypervisor Client ID register + * + * Normal return register usage: + * r0/x0 Return value, TEESMC_RETURN_* + * r1-3/x1-3 Not used + * r4-7/x4-7 Preserved + * + * Ebusy return register usage: + * r0/x0 Return value, TEESMC_RETURN_EBUSY + * r1-3/x1-3 Preserved + * r4-7/x4-7 Preserved + * + * RPC return register usage: + * r0/x0 Return value, TEESMC_RETURN_IS_RPC(val) + * r1-2/x1-2 RPC parameters + * r3-7/x3-7 Resume information, must be preserved + * + * Possible return values: + * TEESMC_RETURN_UNKNOWN_FUNCTION Trusted OS does not recognize this + * function. + * TEESMC_RETURN_OK Call completed, result updated in + * the previously supplied struct + * teesmc32_arg. + * TEESMC_RETURN_EBUSY Trusted OS busy, try again later. + * TEESMC_RETURN_EBADADDR Bad physcial pointer to struct + * teesmc32_arg. + * TEESMC_RETURN_EBADCMD Bad/unknown cmd in struct teesmc32_arg + * TEESMC_RETURN_IS_RPC() Call suspended by RPC call to normal + * world. + */ +#define TEESMC_FUNCID_CALL_WITH_ARG 2 +#define TEESMC32_CALL_WITH_ARG \ + TEESMC_CALL_VAL(TEESMC_32, TEESMC_STD_CALL, TEESMC_OWNER_TRUSTED_OS, \ + TEESMC_FUNCID_CALL_WITH_ARG) +/* Same as TEESMC32_CALL_WITH_ARG but a "fast call". */ +#define TEESMC32_FASTCALL_WITH_ARG \ + TEESMC_CALL_VAL(TEESMC_32, TEESMC_FAST_CALL, TEESMC_OWNER_TRUSTED_OS, \ + TEESMC_FUNCID_CALL_WITH_ARG) + +/* + * Call with struct teesmc64_arg as argument + * + * See description of TEESMC32_CALL_WITH_ARG above, uses struct + * teesmc64_arg in x1 instead. + */ +#define TEESMC64_CALL_WITH_ARG \ + TEESMC_CALL_VAL(TEESMC_64, TEESMC_STD_CALL, TEESMC_OWNER_TRUSTED_OS, \ + TEESMC_FUNCID_CALL_WITH_ARG) +/* Same as TEESMC64_CALL_WITH_ARG but a "fast call". */ +#define TEESMC64_FASTCALL_WITH_ARG \ + TEESMC_CALL_VAL(TEESMC_64, TEESMC_FAST_CALL, TEESMC_OWNER_TRUSTED_OS, \ + TEESMC_FUNCID_CALL_WITH_ARG) + +/* + * Resume from RPC (for example after processing an IRQ) + * + * Call register usage: + * r0/x0 SMC Function ID, + * TEESMC32_CALL_RETURN_FROM_RPC or + * TEESMC32_FASTCALL_RETURN_FROM_RPC + * r1-3/x1-3 Value of r1-3/x1-3 when TEESMC32_CALL_WITH_ARG returned + * TEESMC_RETURN_RPC in r0/x0 + * + * Return register usage is the same as for TEESMC32_CALL_WITH_ARG above. + * + * Possible return values + * TEESMC_RETURN_UNKNOWN_FUNCTION Trusted OS does not recognize this + * function. + * TEESMC_RETURN_OK Original call completed, result + * updated in the previously supplied. + * struct teesmc32_arg + * TEESMC_RETURN_RPC Call suspended by RPC call to normal + * world. + * TEESMC_RETURN_EBUSY Trusted OS busy, try again later. + * TEESMC_RETURN_ERESUME Resume failed, the opaque resume + * information was corrupt. + */ +#define TEESMC_FUNCID_RETURN_FROM_RPC 3 +#define TEESMC32_CALL_RETURN_FROM_RPC \ + TEESMC_CALL_VAL(TEESMC_32, TEESMC_STD_CALL, TEESMC_OWNER_TRUSTED_OS, \ + TEESMC_FUNCID_RETURN_FROM_RPC) +/* Same as TEESMC32_CALL_RETURN_FROM_RPC but a "fast call". */ +#define TEESMC32_FASTCALL_RETURN_FROM_RPC \ + TEESMC_CALL_VAL(TEESMC_32, TEESMC_STD_CALL, TEESMC_OWNER_TRUSTED_OS, \ + TEESMC_FUNCID_RETURN_FROM_RPC) + +/* + * Resume from RPC (for example after processing an IRQ) + * + * See description of TEESMC32_CALL_RETURN_FROM_RPC above, used when + * it's a 64bit call that has returned. + */ +#define TEESMC64_CALL_RETURN_FROM_RPC \ + TEESMC_CALL_VAL(TEESMC_64, TEESMC_STD_CALL, TEESMC_OWNER_TRUSTED_OS, \ + TEESMC_FUNCID_RETURN_FROM_RPC) +/* Same as TEESMC64_CALL_RETURN_FROM_RPC but a "fast call". */ +#define TEESMC64_FASTCALL_RETURN_FROM_RPC \ + TEESMC_CALL_VAL(TEESMC_64, TEESMC_STD_CALL, TEESMC_OWNER_TRUSTED_OS, \ + TEESMC_FUNCID_RETURN_FROM_RPC) + +/* + * From secure monitor to Trusted OS, handle FIQ + * + * A virtual call which is injected by the Secure Monitor when an FIQ is + * raised while in normal world (SCR_NS is set). The monitor restores + * secure architecture registers and secure EL_SP1 and jumps to previous + * secure EL3_ELR. Trusted OS should preserve all general purpose + * registers. + * + * Call register usage: + * r0/x0 SMC Function ID, TEESMC32_CALL_HANDLE_FIQ + * r1-7/x1-7 Not used, but must be preserved + * + * Return register usage: + * Note used + */ +#define TEESMC_FUNCID_CALL_HANDLE_FIQ 0xf000 +#define TEESMC32_CALL_HANDLE_FIQ \ + TEESMC_CALL_VAL(TEESMC_32, TEESMC_FAST_CALL, TEESMC_OWNER_TRUSTED_OS, \ + TEESMC_FUNCID_CALL_HANDLE_FIQ) + +#define TEESMC_RETURN_RPC_PREFIX_MASK 0xFFFF0000 +#define TEESMC_RETURN_RPC_PREFIX 0xFFFF0000 +#define TEESMC_RETURN_RPC_FUNC_MASK 0x0000FFFF + +#define TEESMC_RETURN_GET_RPC_FUNC(ret) ((ret) & TEESMC_RETURN_RPC_FUNC_MASK) + +#define TEESMC_RPC_VAL(func) ((func) | TEESMC_RETURN_RPC_PREFIX) + +/* + * Allocate argument memory for RPC parameter passing. + * Argument memory is used to hold a struct teesmc32_arg. + * + * "Call" register usage: + * r0/x0 This value, TEESMC_RETURN_RPC_ALLOC + * r1/x1 Size in bytes of required argument memory + * r2-7/x2-7 Resume information, must be preserved + * + * "Return" register usage: + * r0/x0 SMC Function ID, TEESMC32_CALL_RETURN_FROM_RPC if it was an + * AArch32 SMC return or TEESMC64_CALL_RETURN_FROM_RPC for + * AArch64 SMC return + * r1/x1 Physical pointer to allocated argument memory, 0 if size + * was 0 or if memory can't be allocated + * r2-7/x2-7 Preserved + */ +#define TEESMC_RPC_FUNC_ALLOC_ARG 0 +#define TEESMC_RETURN_RPC_ALLOC_ARG \ + TEESMC_RPC_VAL(TEESMC_RPC_FUNC_ALLOC_ARG) + +/* + * Allocate payload memory for RPC parameter passing. + * Payload memory is used to hold the memory referred to by struct + * teesmc32_param_memref. + * + * "Call" register usage: + * r0/x0 This value, TEESMC_RETURN_RPC_ALLOC + * r1/x1 Size in bytes of required payload memory + * r2-7/x2-7 Resume information, must be preserved + * + * "Return" register usage: + * r0/x0 SMC Function ID, TEESMC32_CALL_RETURN_FROM_RPC if it was an + * AArch32 SMC return or TEESMC64_CALL_RETURN_FROM_RPC for + * AArch64 SMC return + * r1/x1 Physical pointer to allocated payload memory, 0 if size + * was 0 or if memory can't be allocated + * r2-7/x2-7 Preserved + */ +#define TEESMC_RPC_FUNC_ALLOC_PAYLOAD 1 +#define TEESMC_RETURN_RPC_ALLOC_PAYLOAD \ + TEESMC_RPC_VAL(TEESMC_RPC_FUNC_ALLOC_PAYLOAD) + +/* + * Free memory previously allocated by TEESMC_RETURN_RPC_ALLOC_ARG. + * + * "Call" register usage: + * r0/x0 This value, TEESMC_RETURN_RPC_FREE + * r1/x1 Physical pointer to previously allocated argument memory + * r2-7/x2-7 Resume information, must be preserved + * + * "Return" register usage: + * r0/x0 SMC Function ID, TEESMC32_CALL_RETURN_FROM_RPC if it was an + * AArch32 SMC return or TEESMC64_CALL_RETURN_FROM_RPC for + * AArch64 SMC return + * r1/x1 Not used + * r2-7/x2-7 Preserved + */ +#define TEESMC_RPC_FUNC_FREE_ARG 2 +#define TEESMC_RETURN_RPC_FREE_ARG TEESMC_RPC_VAL(TEESMC_RPC_FUNC_FREE_ARG) + +/* + * Free memory previously allocated by TEESMC_RETURN_RPC_ALLOC_PAYLOAD. + * + * "Call" register usage: + * r0/x0 This value, TEESMC_RETURN_RPC_FREE + * r1/x1 Physical pointer to previously allocated payload memory + * r3-7/x3-7 Resume information, must be preserved + * + * "Return" register usage: + * r0/x0 SMC Function ID, TEESMC32_CALL_RETURN_FROM_RPC if it was an + * AArch32 SMC return or TEESMC64_CALL_RETURN_FROM_RPC for + * AArch64 SMC return + * r1-2/x1-2 Not used + * r3-7/x3-7 Preserved + */ +#define TEESMC_RPC_FUNC_FREE_PAYLOAD 3 +#define TEESMC_RETURN_RPC_FREE_PAYLOAD \ + TEESMC_RPC_VAL(TEESMC_RPC_FUNC_FREE_PAYLOAD) + +/* + * Deliver an IRQ in normal world. + * + * "Call" register usage: + * r0/x0 TEESMC_RETURN_RPC_IRQ + * r1-7/x1-7 Resume information, must be preserved + * + * "Return" register usage: + * r0/x0 SMC Function ID, TEESMC32_CALL_RETURN_FROM_RPC if it was an + * AArch32 SMC return or TEESMC64_CALL_RETURN_FROM_RPC for + * AArch64 SMC return + * r1-7/x1-7 Preserved + */ +#define TEESMC_RPC_FUNC_IRQ 4 +#define TEESMC_RETURN_RPC_IRQ TEESMC_RPC_VAL(TEESMC_RPC_FUNC_IRQ) + +/* + * Do an RPC request. The supplied struct teesmc{32,64}_arg tells which + * request to do and the paramters for the request. The following fields + * are used (the rest are unused): + * - cmd the Request ID + * - ret return value of the request, filled in by normal world + * - num_params number of parameters for the request + * - params the parameters + * - param_attrs attributes of the parameters + * + * "Call" register usage: + * r0/x0 TEESMC_RETURN_RPC_CMD + * r1/x1 Physical pointer to a struct teesmc32_arg if returning from + * a AArch32 SMC or a struct teesmc64_arg if returning from a + * AArch64 SMC, must be preserved, only the data should + * be updated + * r2-7/x2-7 Resume information, must be preserved + * + * "Return" register usage: + * r0/x0 SMC Function ID, TEESMC32_CALL_RETURN_FROM_RPC if it was an + * AArch32 SMC return or TEESMC64_CALL_RETURN_FROM_RPC for + * AArch64 SMC return + * r1-7/x1-7 Preserved + */ +#define TEESMC_RPC_FUNC_CMD 5 +#define TEESMC_RETURN_RPC_CMD TEESMC_RPC_VAL(TEESMC_RPC_FUNC_CMD) + + +/* Returned in r0 */ +#define TEESMC_RETURN_UNKNOWN_FUNCTION 0xFFFFFFFF + +/* Returned in r0 only from Trusted OS functions */ +#define TEESMC_RETURN_OK 0x0 +#define TEESMC_RETURN_EBUSY 0x1 +#define TEESMC_RETURN_ERESUME 0x2 +#define TEESMC_RETURN_EBADADDR 0x3 +#define TEESMC_RETURN_EBADCMD 0x4 +#define TEESMC_RETURN_IS_RPC(ret) \ + (((ret) & TEESMC_RETURN_RPC_PREFIX_MASK) == TEESMC_RETURN_RPC_PREFIX) + +/* + * Returned in r1 by Trusted OS functions if r0 = TEESMC_RETURN_RPC + */ +#define TEESMC_RPC_REQUEST_IRQ 0x0 + +#endif /* TEESMC_H */ diff --git a/core/arch/arm32/include/sm/teesmc_st.h b/core/arch/arm32/include/sm/teesmc_st.h new file mode 100644 index 00000000000..16acb3e9a1b --- /dev/null +++ b/core/arch/arm32/include/sm/teesmc_st.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEESMC_ST_H +#define TEESMC_ST_H + +#define TEESMC_ST_RETURN_NOTAVAIL 0x5700 + +/* + * Get Shared Memory Config + * + * Returns the Secure/Non-secure shared memory config. + * + * Call register usage: + * r0 SMC Function ID, TEESMC32_ST_FASTCALL_GET_SHM_CONFIG + * r1-6 Not used + * r7 Hypervisor Client ID register + * + * Have config return register usage: + * r0 TEESMC_RETURN_OK + * r1 Physical address of start of SHM + * r2 Size of of SHM + * r3 1 if SHM is cached, 0 if uncached. + * r4-7 Preserved + * + * Not available register usage: + * r0 TEESMC_ST_RETURN_NOTAVAIL + * r1-3 Not used + * r4-7 Preserved + */ +#define TEESMC_ST_FUNCID_GET_SHM_CONFIG 0x5700 +#define TEESMC32_ST_FASTCALL_GET_SHM_CONFIG \ + TEESMC_CALL_VAL(TEESMC_32, TEESMC_FAST_CALL, TEESMC_OWNER_TRUSTED_OS, \ + TEESMC_ST_FUNCID_GET_SHM_CONFIG) + +/* + * Configures L2CC mutex + * + * Disables, enables usage of L2CC mutex. Returns or sets physical address + * of L2CC mutex. + * + * Call register usage: + * r0 SMC Function ID, TEESMC32_ST_FASTCALL_L2CC_MUTEX + * r1 TEESMC_ST_L2CC_MUTEX_GET_ADDR Get physical address of mutex + * TEESMC_ST_L2CC_MUTEX_SET_ADDR Set physical address of mutex + * TEESMC_ST_L2CC_MUTEX_ENABLE Enable usage of mutex + * TEESMC_ST_L2CC_MUTEX_DISABLE Disable usage of mutex + * r2 if r1 == TEESMC_ST_L2CC_MUTEX_SET_ADDR, physical address of mutex + * r3-6 Not used + * r7 Hypervisor Client ID register + * + * Have config return register usage: + * r0 TEESMC_RETURN_OK + * r1 Preserved + * r2 if r1 == 0, physical address of L2CC mutex + * r3-7 Preserved + * + * Error return register usage: + * r0 TEESMC_ST_RETURN_NOTAVAIL Physical address not available + * TEESMC_RETURN_EBADADDR Bad supplied physical address + * TEESMC_RETURN_EBADCMD Unsupported value in r1 + * r1-7 Preserved + */ +#define TEESMC_ST_L2CC_MUTEX_GET_ADDR 0 +#define TEESMC_ST_L2CC_MUTEX_SET_ADDR 1 +#define TEESMC_ST_L2CC_MUTEX_ENABLE 2 +#define TEESMC_ST_L2CC_MUTEX_DISABLE 3 +#define TEESMC_ST_FUNCID_L2CC_MUTEX 0x5701 +#define TEESMC32_ST_FASTCALL_L2CC_MUTEX \ + TEESMC_CALL_VAL(TEESMC_32, TEESMC_FAST_CALL, TEESMC_OWNER_TRUSTED_OS, \ + TEESMC_ST_FUNCID_L2CC_MUTEX) + +/* + * Allocate payload memory for RPC parameter passing. + * + * "Call" register usage: + * r0/x0 This value, TEESMC_RETURN_ST_RPC_ALLOC_PAYLOAD + * r1/x1 Size in bytes of required payload memory + * r2/x2 Not used + * r3-7/x3-7 Resume information, must be preserved + * + * "Return" register usage: + * r0/x0 SMC Function ID, TEESMC32_CALL_RETURN_FROM_RPC if it was an + * AArch32 SMC return or TEESMC64_CALL_RETURN_FROM_RPC for + * AArch64 SMC return + * r1/x1 Physical pointer to allocated payload memory, 0 if size + * was 0 or if memory can't be allocated + * r2/x2 Shared memory cookie used when freeing the memory + * r3-7/x3-7 Preserved + */ +#define TEESMC_ST_RPC_FUNC_ALLOC_PAYLOAD 0x5700 +#define TEESMC_RETURN_ST_RPC_ALLOC_PAYLOAD \ + TEESMC_RPC_VAL(TEESMC_ST_RPC_FUNC_ALLOC_PAYLOAD) + + +/* + * Free memory previously allocated by TEESMC_RETURN_ST_RPC_ALLOC_PAYLOAD + * + * "Call" register usage: + * r0/x0 This value, TEESMC_RETURN_ST_RPC_FREE_PAYLOAD + * r1/x1 Shared memory cookie belonging to this payload memory + * r2-7/x2-7 Resume information, must be preserved + * + * "Return" register usage: + * r0/x0 SMC Function ID, TEESMC32_CALL_RETURN_FROM_RPC if it was an + * AArch32 SMC return or TEESMC64_CALL_RETURN_FROM_RPC for + * AArch64 SMC return + * r2-7/x2-7 Preserved + */ +#define TEESMC_ST_RPC_FUNC_FREE_PAYLOAD 0x5701 +#define TEESMC_RETURN_ST_RPC_FREE_PAYLOAD \ + TEESMC_RPC_VAL(TEESMC_ST_RPC_FUNC_FREE_PAYLOAD) + +/* Overriding default UID since the interface is extended + * 384fb3e0-e7f8-11e3-af63-0002a5d5c51b + */ +#define TEESMC_ST_UID_R0 0x384fb3e0 +#define TEESMC_ST_UID_R1 0xe7f811e3 +#define TEESMC_ST_UID_R2 0xaf630002 +#define TEESMC_ST_UID32_R3 0xa5d5c51b +#define TEESMC_ST_UID64_R3 0xa5d5c51c + +#define TEESMC_ST_REVISION_MAJOR 1 +#define TEESMC_ST_REVISION_MINOR 0 + +/* + * UUID for OP-TEE + * 486178e0-e7f8-11e3-bc5e-0002a5d5c51b + */ +#define TEESMC_OS_OPTEE_UUID_R0 0x486178e0 +#define TEESMC_OS_OPTEE_UUID_R1 0xe7f811e3 +#define TEESMC_OS_OPTEE_UUID_R2 0xbc5e0002 +#define TEESMC_OS_OPTEE_UUID_R3 0xa5d5c51b + +#define TEESMC_OS_OPTEE_REVISION_MAJOR 1 +#define TEESMC_OS_OPTEE_REVISION_MINOR 0 + +#endif /*TEESMC_ST_H*/ diff --git a/core/arch/arm32/include/tee/entry.h b/core/arch/arm32/include/tee/entry.h new file mode 100644 index 00000000000..0976432166b --- /dev/null +++ b/core/arch/arm32/include/tee/entry.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TEE_ENTRY_H +#define TEE_ENTRY_H + +#include + +/* These functions are overridable by the specific target */ +void tee_entry_get_api_call_count(struct thread_smc_args *args); +void tee_entry_get_api_uuid(struct thread_smc_args *args); +void tee_entry_get_api_revision(struct thread_smc_args *args); +void tee_entry_get_os_uuid(struct thread_smc_args *args); +void tee_entry_get_os_revision(struct thread_smc_args *args); + +/* + * Returns the number of calls recognized by tee_entry(). Used by the + * specific target to calculate the total number of supported calls when + * overriding tee_entry_get_api_call_count(). + */ +size_t tee_entry_generic_get_api_call_count(void); + +void tee_entry(struct thread_smc_args *args); + +#endif /*TEE_ENTRY_H*/ diff --git a/core/arch/arm32/kernel/chip_services.c b/core/arch/arm32/kernel/chip_services.c new file mode 100644 index 00000000000..e9d753767ee --- /dev/null +++ b/core/arch/arm32/kernel/chip_services.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include + +#include + +/* + * enable_secure_wd - This function enables secure watchdog + */ +void enable_secure_wd(void) +{ + /* + * Only a stub. + * Real implementation is missing. + */ +} diff --git a/core/arch/arm32/kernel/misc.S b/core/arch/arm32/kernel/misc.S new file mode 100644 index 00000000000..15ff5fd3998 --- /dev/null +++ b/core/arch/arm32/kernel/misc.S @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +FUNC get_core_pos , : + read_mpidr r0 + /* Calculate CorePos = (ClusterId * 4) + CoreId */ + and r1, r0, #MPIDR_CPU_MASK + and r0, r0, #MPIDR_CLUSTER_MASK + add r0, r1, r0, LSR #6 + bx lr +END_FUNC get_core_pos diff --git a/core/arch/arm32/kernel/sub.mk b/core/arch/arm32/kernel/sub.mk new file mode 100644 index 00000000000..7bc483efc75 --- /dev/null +++ b/core/arch/arm32/kernel/sub.mk @@ -0,0 +1,27 @@ +srcs-y += tee_core_trace.c +cflags-tee_core_trace.c-y += -Wno-format +cflags-tee_core_trace.c-y += -Wno-format-nonliteral -Wno-format-security + +srcs-y += tee_ta_manager.c +cflags-tee_ta_manager.c-y += -Wno-declaration-after-statement -Wno-format +cflags-tee_ta_manager.c-y += -Wno-unused-parameter +cflags-tee_ta_manager.c-y += -Wno-format-nonliteral -Wno-format-security + + +srcs-y += tee_sleep_services.c +cflags-tee_sleep_services.c-y += -Wno-unused-parameter + +srcs-y += tee_time.c +cflags-tee_time.c-y += -Wno-unused-parameter + +srcs-y += chip_services.c + +srcs-y += tee_misc.c +srcs-y += tee_time_unpg.c +srcs-y += tz_proc.S +srcs-y += tz_ssvce.S +srcs-y += tee_l2cc_mutex.c + +srcs-y += thread_asm.S +srcs-y += thread.c +srcs-y += misc.S diff --git a/core/arch/arm32/kernel/tee_core_trace.c b/core/arch/arm32/kernel/tee_core_trace.c new file mode 100644 index 00000000000..7b8bc09b60c --- /dev/null +++ b/core/arch/arm32/kernel/tee_core_trace.c @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#define STR_TRACE_CORE "TEE-CORE-TZ" +#include + +#ifdef WITH_UART_DRV +#include +#include +#else +#include +#endif + +/*****************************************************************************/ + +/* Default trace level */ +int _trace_level = CFG_TEE_CORE_LOG_LEVEL; + + +#ifdef WITH_UART_DRV +static void output_string(const char *str) +{ + const char *p = str; + + while (*p) { + uart_putc(*p, UART1_BASE); + p++; + } +} + +static void output_flush(void) +{ + uart_flush_tx_fifo(UART1_BASE); +} +#else +#define output_string(x) __asc_xmit(x) +#define output_flush() __asc_flush() +#endif + +/*****************************************************************************/ + +void core_trace_test(void) +{ + INMSG("level: [%d]", _trace_level); + IMSG("current trace level = %d", _trace_level); + IMSG("Without args"); + AMSG("[%d] and [%s]", TRACE_ALWAYS, "TRACE_ALWAYS"); + EMSG("[%d] and [%s]", TRACE_ERROR, "TRACE_ERROR"); + IMSG("[%d] and [%s]", TRACE_INFO, "TRACE_INFO"); + DMSG("[%d] and [%s]", TRACE_DEBUG, "TRACE_DEBUG"); + FMSG("[%d] and [%s]", TRACE_FLOW, "TRACE_FLOW"); + AMSG_RAW("Raw trace in TEE CORE with level [%s]", "TRACE_ALWAYS"); + AMSG_RAW(" __ end of raw trace\n"); + DMSG_RAW("Raw trace in TEE CORE with level [%s]", "TRACE_DEBUG"); + DMSG_RAW(" __ end of raw trace\n"); + OUTMSG(""); +} + +/*****************************************************************************/ + +void set_trace_level(int level) +{ + if (((int)level >= TRACE_MIN) && (level <= TRACE_MAX)) + _trace_level = level; + else + AMSG("Can't set level [%d]", level); + + core_trace_test(); + AMSG_RAW("\nLevel set to [%d]\n", _trace_level); +} + +int get_trace_level(void) +{ + return _trace_level; +} + +/*****************************************************************************/ + +static const char const *_trace_level_to_string[] = { + "NONE", "ALW", "ERR", "INF", "DBG", "FLW" }; + +/* Format trace of user ta. Inline with kernel ta */ +static int format_trace(const char *function, int line, int level, + const char *prefix, const char *in, char *out) +{ + int nb_char = MAX_PRINT_SIZE; + const char *func; + int thread_id = 0; + + if (function) { +#ifdef TRACE_FUNC_LENGTH_CST + char func_buf[MAX_FUNC_PRINT_SIZE]; + int flen = strlen(function); + + /* Limit the function name to MAX_FUNC_PRINT_SIZE characters. */ + strncpy(func_buf, function, flen > MAX_FUNC_PRINT_SIZE ? + (MAX_FUNC_PRINT_SIZE - 1) : flen); + if (flen < (MAX_FUNC_PRINT_SIZE - 1)) { + memset(func_buf + flen, 0x20, + (MAX_FUNC_PRINT_SIZE - flen)); + } + func_buf[MAX_FUNC_PRINT_SIZE - 1] = '\0'; + func = func_buf; +#else + func = function; +#endif + + nb_char = + snprintf(out, MAX_PRINT_SIZE, "%s [%p] %s:%s:%d: %s\n", + _trace_level_to_string[level], thread_id, prefix, + func, line, in); + } else { + memcpy(out, in, MAX_PRINT_SIZE); + + /* we need to add \n and a \0 at end of the string if not + * present. We also set nb_char to the string length, including + * appended chars. */ +#if (MAX_PRINT_SIZE <= 2) +#error "cannot support MAX_PRINT_SIZE lesser than 3!" +#endif + nb_char = 0; + while (*out) { + out++; + if (++nb_char == MAX_PRINT_SIZE) { + /* force the 2 last bytes */ + *(out - 2) = '\n'; + *(out - 1) = '\0'; + return MAX_PRINT_SIZE - 1; + } + } + if (*(out - 1) != '\n') { + /* force last char to \n and append the \0 */ + *(out) = '\n'; + *(out + 1) = '\0'; + nb_char++; + } + } + return nb_char; +} + + +int _dprintf(const char *function, int line, int level, const char *prefix, + const char *fmt, ...) +{ + char to_format[MAX_PRINT_SIZE]; + char formatted[MAX_PRINT_SIZE]; + va_list ap; + int nb; + + va_start(ap, fmt); + (void)vsnprintf(to_format, sizeof(to_format), fmt, ap); + va_end(ap); + + nb = format_trace(function, line, level, prefix, to_format, formatted); + + /* + * dprint is making use of the uart. + * a shared mem / circular buffer based trace could be used instead + */ + output_string(formatted); + + return nb; +} + +int _dprintf_hwsync(const char *function, int line, const char *fmt, ...) +{ + char to_format[MAX_PRINT_SIZE]; + char formatted[MAX_PRINT_SIZE]; + va_list ap; + int nb; + + va_start(ap, fmt); + (void)vsnprintf(to_format, sizeof(to_format), fmt, ap); + va_end(ap); + + nb = format_trace(function, line, TRACE_ALWAYS, "HWSYNC", to_format, + formatted); + + /* note: no contention or synchro handle with other CPU core ! */ + output_flush(); + output_string(formatted); + output_flush(); + + return nb; +} + +/*****************************************************************************/ diff --git a/core/arch/arm32/kernel/tee_l2cc_mutex.c b/core/arch/arm32/kernel/tee_l2cc_mutex.c new file mode 100644 index 00000000000..6dedcf2e02c --- /dev/null +++ b/core/arch/arm32/kernel/tee_l2cc_mutex.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * l2cc_mutex_va holds teecore virtual address of TZ L2CC mutex or NULL. + * + * l2cc_mutex_pa holds TZ L2CC mutex physical address. It is relevant only + * if 'l2cc_mutex_va' hold a non-NULL address. + * + * l2cc_mutex_mm hold teecore mm structure used to allocate TZ L2CC mutex, + * if allocated. Otherwise, it is NULL. + */ +#define MUTEX_SZ sizeof(uint32_t) + +static uint32_t *l2cc_mutex_va; +static uint32_t l2cc_mutex_pa; +static tee_mm_entry_t *l2cc_mutex_mm; + +/* + * Allocate public RAM to get a L2CC mutex to shared with NSec. + * Return 0 on success. + */ +static int alloc_l2cc_mutex(void) +{ + uint32_t va; + + if ((l2cc_mutex_va != NULL) || (l2cc_mutex_mm != NULL)) + return -1; + + l2cc_mutex_mm = tee_mm_alloc(&tee_mm_pub_ddr, MUTEX_SZ); + if (l2cc_mutex_mm == NULL) + return -1; + + l2cc_mutex_pa = tee_mm_get_smem(l2cc_mutex_mm); + + if (core_pa2va(l2cc_mutex_pa, &va)) + return -1; + + *(uint32_t *)va = 0; + l2cc_mutex_va = (uint32_t *)va; + return 0; +} + +/* + * tee_l2cc_mutex_configure - Handle L2 mutex configuration requests from NSec + * + * Policy: + * - if NSec did not register a L2 mutex, default allocate it in public RAM. + * - if NSec disables L2 mutex, disable the current mutex and unregister it. + */ +TEE_Result tee_l2cc_mutex_configure(uint32_t service_id, uint32_t *mutex) +{ + uint32_t addr, va; + int ret = TEE_SUCCESS; + + /* + * Enable L2CC: NSec allows teecore to run safe outer maintance + * with shared mutex. + * Disable L2CC: NSec will run outer maintenance with locking + * shared mutex. teecore cannot run outer maintenance. + * Set L2CC: NSec proposes a Shared Memory locaiotn for the outer + * maintenance shared mutex. + * Get L2CC: NSec requests the outer maintenance shared mutex + * location. If NSec has successufully registered one, + * return its location, otherwise, allocated one in NSec + * and provided NSec the physical location. + */ + switch (service_id) { + case SERVICEID_ENABLE_L2CC_MUTEX: + if (l2cc_mutex_va == 0) { + ret = alloc_l2cc_mutex(); + if (ret) + return TEE_ERROR_GENERIC; + } + core_l2cc_mutex_set(l2cc_mutex_va); + break; + case SERVICEID_DISABLE_L2CC_MUTEX: + if (l2cc_mutex_mm) { + tee_mm_free(l2cc_mutex_mm); + l2cc_mutex_mm = NULL; + } + l2cc_mutex_va = NULL; + core_l2cc_mutex_set(NULL); + break; + case SERVICEID_GET_L2CC_MUTEX: + if (l2cc_mutex_va == NULL) { + ret = alloc_l2cc_mutex(); + if (ret) + return TEE_ERROR_GENERIC; + } + *mutex = l2cc_mutex_pa; + break; + case SERVICEID_SET_L2CC_MUTEX: + if (l2cc_mutex_va != NULL) + return TEE_ERROR_BAD_PARAMETERS; + addr = *mutex; + if (core_pbuf_is(CORE_MEM_NSEC_SHM, addr, MUTEX_SZ) == false) + return TEE_ERROR_BAD_PARAMETERS; + if (core_pa2va(addr, (uint32_t *)&va)) + return TEE_ERROR_BAD_PARAMETERS; + l2cc_mutex_pa = addr; + l2cc_mutex_va = (uint32_t *)va; + break; + default: + return TEE_ERROR_GENERIC; + } + + return ret; +} diff --git a/core/arch/arm32/kernel/tee_misc.c b/core/arch/arm32/kernel/tee_misc.c new file mode 100644 index 00000000000..0ad2576ac5a --- /dev/null +++ b/core/arch/arm32/kernel/tee_misc.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + + +#include +#include + +static uint8_t tee_b2hs_add_base(uint8_t in) +{ + if (in > 9) + return in + 55; + else + return in + 48; +} + +static int tee_hs2b_rem_base(uint8_t in, uint8_t *out) +{ + if (in < 48 || in > 70 || (in > 57 && in < 65)) + return -1; + + if (in < 58) + *out = in - 48; + else + *out = in - 55; + + return 0; +} + +uint32_t tee_b2hs(uint8_t *b, uint8_t *hs, uint32_t blen, uint32_t hslen) +{ + uint32_t i = 0; + + if (blen * 2 + 1 > hslen) + return 0; + + for (; i < blen; i++) { + hs[i * 2 + 1] = tee_b2hs_add_base(b[i] & 0xf); + hs[i * 2] = tee_b2hs_add_base(b[i] >> 4); + } + hs[blen * 2] = 0; + + return blen * 2; +} + +uint32_t tee_hs2b(uint8_t *hs, uint8_t *b, uint32_t hslen, uint32_t blen) +{ + uint32_t i = 0; + uint32_t len = TEE_HS2B_BBUF_SIZE(hslen); + uint8_t hi; + uint8_t lo; + + if (len > blen) + return 0; + + for (; i < len; i++) { + if (tee_hs2b_rem_base(hs[i * 2], &hi)) + return 0; + if (tee_hs2b_rem_base(hs[i * 2 + 1], &lo)) + return 0; + b[i] = (hi << 4) + lo; + } + + return len; +} diff --git a/core/arch/arm32/kernel/tee_sleep_services.c b/core/arch/arm32/kernel/tee_sleep_services.c new file mode 100644 index 00000000000..03cdfa5eeee --- /dev/null +++ b/core/arch/arm32/kernel/tee_sleep_services.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + + +#ifdef DMAC_PREFOT_REG_ADDR +static uint32_t dmac_prefot; +#endif + +#if defined(DMAC_SWSEG_START_ADDR) && defined(DMAC_SWDEG_START_ADDR) +static uint32_t dmac_swseg[DMAC_SWSREG_NUM_REGS]; +static uint32_t dmac_swdeg[DMAC_SWDREG_NUM_REGS]; +#endif + +TEE_Result tee_sleep_save_restore_vape(bool save) +{ +#ifdef DMAC_PREFOT_REG_ADDR + if (save) + dmac_prefot = IO(DMAC_PREFOT_REG_ADDR); + else + IO(DMAC_PREFOT_REG_ADDR) = dmac_prefot; +#endif + +#if defined(DMAC_SWSEG_START_ADDR) && defined(DMAC_SWDEG_START_ADDR) + { + uint32_t i; + + if (save) { + for (i = 0; i < DMAC_SWSREG_NUM_REGS; i++) + dmac_swseg[i] = + IO(DMAC_SWSEG_START_ADDR + i * 4); + for (i = 0; i < DMAC_SWDREG_NUM_REGS; i++) + dmac_swdeg[i] = + IO(DMAC_SWDEG_START_ADDR + i * 4); + } else { + for (i = 0; i < DMAC_SWSREG_NUM_REGS; i++) + IO(DMAC_SWSEG_START_ADDR + i * 4) = + dmac_swseg[i]; + for (i = 0; i < DMAC_SWDREG_NUM_REGS; i++) + IO(DMAC_SWDEG_START_ADDR + i * 4) = + dmac_swdeg[i]; + } + } +#endif + + return TEE_SUCCESS; +} diff --git a/core/arch/arm32/kernel/tee_ta_manager.c b/core/arch/arm32/kernel/tee_ta_manager.c new file mode 100644 index 00000000000..1ddbb54d443 --- /dev/null +++ b/core/arch/arm32/kernel/tee_ta_manager.c @@ -0,0 +1,1700 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "user_ta_header.h" +#include +#include +#include +#include +#include + + +/* Use this invalid ID for a static TA, since + * session is not needed for calling static TA. + */ +#define TEE_SESSION_ID_STATIC_TA 0xFFFFFFFF + +#define TEE_TA_STACK_ALIGNMENT 8 + +enum tee_user_ta_func { + USER_TA_FUNC_OPEN_CLIENT_SESSION = 0, + USER_TA_FUNC_CLOSE_CLIENT_SESSION, + USER_TA_FUNC_INVOKE_COMMAND +}; + +typedef enum { + COMMAND_INVOKE_COMMAND = 0, + COMMAND_OPEN_SESSION, + COMMAND_CREATE_ENTRY_POINT, + COMMAND_CLOSE_SESSION, + COMMAND_DESTROY_ENTRY_POINT, +} command_t; + +/* Only one session is running in the single threaded solution */ +static struct tee_ta_session *tee_rs; + +/* Enters a user TA */ +static TEE_Result tee_user_ta_enter(TEE_ErrorOrigin *err, + struct tee_ta_session *session, + enum tee_user_ta_func func, + uint32_t cancel_req_to, uint32_t cmd, + struct tee_ta_param *param); + +static TEE_Result tee_ta_param_pa2va(struct tee_ta_session *sess, + struct tee_ta_param *param); + +struct param_ta { + struct tee_ta_session *sess; + uint32_t cmd; + struct tee_ta_param *param; + TEE_Result res; +}; + +static TEE_Result tee_ta_rpc_free(struct tee_ta_nwumap *map); + +static void jumper_invokecommand(void *voidargs) +{ + struct param_ta *args = (struct param_ta *)voidargs; + + INMSG(""); + args->res = args->sess->ctx->static_ta->invoke_command_entry_point( + (void *)args->sess->user_ctx, + (uint32_t)args->cmd, + (uint32_t)args->param->types, + (TEE_Param *)args->param->params); + OUTMSG("%lx", args->res); +} + +static void jumper_opensession(void *voidargs) +{ + struct param_ta *args = (struct param_ta *)voidargs; + + INMSG(""); + args->res = args->sess->ctx->static_ta->open_session_entry_point( + (uint32_t)args->param->types, + (TEE_Param *)args->param->params, + (void **)&args->sess->user_ctx); + OUTMSG("%lx", args->res); +} + +static void jumper_createentrypoint(void *voidargs) +{ + struct param_ta *args = (struct param_ta *)voidargs; + + INMSG(""); + args->res = args->sess->ctx->static_ta->create_entry_point(); + OUTMSG("%lx", args->res); +} + +static void jumper_closesession(void *voidargs) +{ + struct param_ta *args = (struct param_ta *)voidargs; + + INMSG(""); + args->sess->ctx->static_ta->close_session_entry_point( + (void *)args->sess->user_ctx); + args->res = TEE_SUCCESS; + OUTMSG("%lx", args->res); +} + +static void jumper_destroyentrypoint(void *voidargs) +{ + struct param_ta *args = (struct param_ta *)voidargs; + + INMSG(""); + args->sess->ctx->static_ta->destroy_entry_point(); + args->res = TEE_SUCCESS; + OUTMSG("%lx", args->res); +} + +/* Stack size is updated to take into account */ +/* the size of the needs of the tee internal libs */ + +static TEE_Result invoke_ta(struct tee_ta_session *sess, uint32_t cmd, + struct tee_ta_param *param, command_t commandtype) +{ + struct param_ta ptas; + + ptas.sess = sess; + ptas.cmd = cmd; + ptas.param = param; + ptas.res = TEE_ERROR_TARGET_DEAD; + + tee_rs = sess; + + switch (commandtype) { + case COMMAND_INVOKE_COMMAND: + jumper_invokecommand(&ptas); + break; + case COMMAND_OPEN_SESSION: + jumper_opensession(&ptas); + break; + case COMMAND_CREATE_ENTRY_POINT: + jumper_createentrypoint(&ptas); + break; + case COMMAND_CLOSE_SESSION: + jumper_closesession(&ptas); + break; + case COMMAND_DESTROY_ENTRY_POINT: + jumper_destroyentrypoint(&ptas); + break; + default: + EMSG("Do not know how to run the command %d", commandtype); + ptas.res = TEE_ERROR_GENERIC; + break; + } + + tee_rs = NULL; + + OUTRMSG(ptas.res); + return ptas.res; +} + +/* set trace level for all installed TAs (TA generic code) */ +int tee_ta_set_trace_level(int level) +{ + struct tee_ta_ctx *ctx; + + if ((level > TRACE_MAX) && (level < TRACE_MIN)) + return -1; + + TAILQ_FOREACH(ctx, &tee_ctxes, link) { + if (ctx->static_ta) + ctx->static_ta->prop_tracelevel = level; + + /* non-static TA should be done too */ + } + return 0; +} + +/*----------------------------------------------------------------------------- + * Find TA in session list based on a UUID (input) + * Returns a pointer to the session + *---------------------------------------------------------------------------*/ +static struct tee_ta_ctx *tee_ta_context_find(const TEE_UUID *uuid) +{ + struct tee_ta_ctx *ctx; + + TAILQ_FOREACH(ctx, &tee_ctxes, link) { + if (memcmp(&ctx->head->uuid, uuid, sizeof(TEE_UUID)) == 0) + return ctx; + } + + return NULL; +} + +static void tee_ta_init_got(struct tee_ta_ctx *const ctx) +{ + uint32_t *ptr; + uint32_t *end_ptr; + uint32_t va_start; + + /* + * GOT and find_service_addr follows right after ro section. + */ + if ((TA_HEAD_GOT_MASK & ctx->head->rel_dyn_got_size) == 0) + return; + + va_start = ctx->load_addr; + + ptr = (uint32_t *)(tee_ta_get_exec(ctx) + ctx->head->ro_size); + end_ptr = (uint32_t *)((uint32_t) ptr + + (TA_HEAD_GOT_MASK & ctx->head->rel_dyn_got_size)); + + while (ptr < end_ptr) { + *ptr += va_start; +#ifdef PAGER_DEBUG_PRINT + DMSG("GOT [0x%x] = 0x%x", ptr, *ptr); +#endif + ptr++; + } +} + +static void tee_ta_init_zi(struct tee_ta_ctx *const ctx) +{ + /* setup ZI data */ + uint32_t start = tee_ta_get_exec(ctx) + + ctx->head->rw_size + ctx->head->ro_size; + + memset((void *)start, 0, ctx->head->zi_size); +} + +static void tee_ta_init_serviceaddr(struct tee_ta_ctx *const ctx) +{ + /* + * Kernel TA + * + * Find service follows right after GOT. + */ + uint32_t saddr = tee_ta_get_exec(ctx) + ctx->head->ro_size + + (ctx->head->rel_dyn_got_size & TA_HEAD_GOT_MASK); + uint32_t *fsaddr = (uint32_t *)saddr; + + *fsaddr = 0; /* we do not have any services */ + +#ifdef PAGER_DEBUG_PRINT + DMSG("find_service_addr [0x%x] = 0x%x", fsaddr, *fsaddr); +#endif +} + +/* + * Process rel.dyn + */ +static void tee_ta_init_reldyn(struct tee_ta_ctx *const ctx) +{ + uint32_t rel_dyn_size = ctx->head->rel_dyn_got_size >> 16; + uint32_t n; + uint32_t saddr = + tee_ta_get_exec(ctx) + ctx->head->ro_size - rel_dyn_size; + + for (n = 0; n < rel_dyn_size; n += sizeof(struct ta_rel_dyn)) { + struct ta_rel_dyn *rel_dyn = (struct ta_rel_dyn *)(saddr + n); + uint32_t *data; + + if (rel_dyn->info != 0x17) { + DMSG("Unknown rel_dyn info 0x%x", rel_dyn->info); + TEE_ASSERT(0); + } + + data = (uint32_t *)(ctx->load_addr + rel_dyn->addr); + *data += ctx->load_addr; +#ifdef PAGER_DEBUG_PRINT + DMSG("rel.dyn [0x%x] = 0x%x", data, *data); +#endif + } +} + +/* + * Setup global variables initialized from TEE Core + */ +static void tee_ta_init_heap(struct tee_ta_ctx *const ctx, uint32_t heap_size) +{ + uint32_t *data; + tee_uaddr_t heap_start_addr; + + /* + * User TA + * + * Heap base follows right after GOT + */ + + /* XXX this function shouldn't know this mapping */ + heap_start_addr = ((TEE_DDR_VLOFFSET + 1) << SECTION_SHIFT) - heap_size; + + data = (uint32_t *)(tee_ta_get_exec(ctx) + ctx->head->ro_size + + (ctx->head->rel_dyn_got_size & TA_HEAD_GOT_MASK)); + + *data = heap_start_addr; +#ifdef PAGER_DEBUG_PRINT + DMSG("heap_base [0x%x] = 0x%x", data, *data); +#endif +} + +/*----------------------------------------------------------------------------- + * Loads TA header and hashes. + * Verifies the TA signature. + * Returns session ptr and TEE_Result. + *---------------------------------------------------------------------------*/ +static TEE_Result tee_ta_load(const kta_signed_header_t *signed_ta, + struct tee_ta_ctx **ta_ctx) +{ + /* ta & ta_session is assumed to be != NULL from previous checks */ + TEE_Result res; + uint32_t size; + size_t nbr_hashes; + int head_size; + uint32_t hash_type_size; + uint32_t hash_size; + void *head = NULL; + void *ptr = NULL; + uint32_t heap_size = 0; /* gcc warning */ + struct tee_ta_ctx *ctx = NULL; + ta_head_t *ta = + (void *)((uint8_t *)signed_ta + signed_ta->size_of_signed_header); + + /* + * ------------------------------------------------------------------ + * 1st step: load in secure memory and check consisteny, signature. + * Note: this step defines the user/kernel priviledge of the TA. + * ------------------------------------------------------------------ + */ + + /* + * Check that the GOT ends up at a properly aligned address. + * See tee_ta_load_page() for update of GOT. + */ + if ((ta->ro_size % 4) != 0) { + DMSG("Bad ro_size %u", ta->ro_size); + return TEE_ERROR_BAD_FORMAT; + } + + nbr_hashes = ((ta->ro_size + ta->rw_size) >> SMALL_PAGE_SHIFT) + 1; + if (nbr_hashes > TEE_PVMEM_PSIZE) + return TEE_ERROR_OUT_OF_MEMORY; + +#ifdef CFG_NO_TA_HASH_SIGN + hash_type_size = 0; +#else + /* COPY HEADERS & HASHES: ta_head + ta_func_head(s) + hashes */ + if (tee_hash_get_digest_size(ta->hash_type, &hash_type_size) != + TEE_SUCCESS) { + DMSG("warning: invalid signed header: invalid hash id found!"); + return TEE_ERROR_SECURITY; + } +#endif + hash_size = hash_type_size * nbr_hashes; + head_size = + sizeof(ta_head_t) + + ta->nbr_func * sizeof(ta_func_head_t) + hash_size; + + head = malloc(head_size); + if (head == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + /* cpy headers from normal world memory */ + memcpy(head, ta, head_size - hash_size); + + /* cpy hashes from normal world memory */ + ptr = + (void *)((uint8_t *)head + + sizeof(ta_head_t) + ta->nbr_func * sizeof(ta_func_head_t)); + + memcpy(ptr, (void *)((uint8_t *)ta + sizeof(ta_head_t) + + ta->nbr_func * sizeof(ta_func_head_t) + + ta->ro_size + ta->rw_size), hash_size); + + /* COPY SIGNATURE: alloc signature */ + ptr = malloc(signed_ta->size_of_signed_header); + if (ptr == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto error_return; + } + + /* cpy signature to secure memory */ + memcpy(ptr, signed_ta, signed_ta->size_of_signed_header); + + /* + * We may check signed TAs in this place + */ + + + /* + * End of check of signed header from secure: + * hashes are safe and validated. + */ + + free(ptr); + ptr = NULL; + + /* + * ------------------------------------------------------------------ + * 2nd step: Register context + * Alloc and init the ta context structure, alloc physvical/virtual + * memories to store/map the TA. + * ------------------------------------------------------------------ + */ + + /* + * Register context + */ + + /* code below must be protected by mutex (multi-threaded) */ + ctx = calloc(1, sizeof(struct tee_ta_ctx)); + if (ctx == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto error_return; + } + TAILQ_INIT(&ctx->open_sessions); + TAILQ_INIT(&ctx->cryp_states); + TAILQ_INIT(&ctx->objects); + TAILQ_INIT(&ctx->storage_enums); + ctx->head = (ta_head_t *)head; + + /* by default NSec DDR: starts at TA function code. */ + ctx->nmem = (void *)((uint32_t) ta + sizeof(ta_head_t) + + ta->nbr_func * sizeof(ta_func_head_t)); + + ctx->num_res_funcs = ctx->head->zi_size >> 20; + ctx->head->zi_size &= 0xfffff; + if (ctx->num_res_funcs > ctx->head->nbr_func) { + res = TEE_ERROR_BAD_FORMAT; + goto error_return; + } + + /* full required execution size (not stack etc...) */ + size = ctx->head->ro_size + ctx->head->rw_size + ctx->head->zi_size; + + if (ctx->num_res_funcs == 2) { + ta_func_head_t *ta_func_head = + (ta_func_head_t *)((uint32_t) ctx->head + + sizeof(ta_head_t)); + + struct user_ta_sub_head *sub_head = + (struct user_ta_sub_head *)&ta_func_head[ctx->head-> + nbr_func - + ctx-> + num_res_funcs]; + /* man_flags: mandatory flags */ + uint32_t man_flags = TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR; + uint32_t opt_flags = man_flags | TA_FLAG_SINGLE_INSTANCE | + TA_FLAG_MULTI_SESSION | TA_FLAG_UNSAFE_NW_PARAMS; + + /* + * sub_head is the end area of func_head; the 2 last + * (2 'resisdent func') func_head area. + * sub_head structure is... twice the func_head struct. magic. + * sub_head stores the flags, heap_size, stack_size. + */ + TEE_ASSERT((sizeof(struct user_ta_sub_head)) == + (2 * sizeof(struct user_ta_func_head))); + + /* + * As we support only UserTA: assue all TA are user TA ! + */ + sub_head->flags |= TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR; + + /* check input flags bitmask consistency and save flags */ + if ((sub_head->flags & opt_flags) != sub_head->flags || + (sub_head->flags & man_flags) != man_flags) { + EMSG("TA flag issue: flags=%x opt=%X man=%X", + sub_head->flags, opt_flags, man_flags); + res = TEE_ERROR_BAD_FORMAT; + goto error_return; + } + + ctx->flags = sub_head->flags; + + /* Check if multi instance && single session config */ + if (((ctx->flags & TA_FLAG_SINGLE_INSTANCE) == 0) && + ((ctx->flags & TA_FLAG_MULTI_SESSION) == 0)) { + /* + * assume MultiInstance/SingleSession, + * same as MultiInstance/MultiSession + */ + ctx->flags |= TA_FLAG_MULTI_SESSION; + } + + /* Ensure proper aligment of stack */ + ctx->stack_size = TEE_ROUNDUP(sub_head->stack_size, + TEE_TA_STACK_ALIGNMENT); + + heap_size = sub_head->heap_size; + + if (ctx->stack_size + heap_size > SECTION_SIZE) { + EMSG("Too large combined stack and HEAP"); + res = TEE_ERROR_OUT_OF_MEMORY; + goto error_return; + } + + /* + * Allocate heap and stack + */ + ctx->mm_heap_stack = + tee_mm_alloc(&tee_mm_sec_ddr, SECTION_SIZE); + if (ctx->mm_heap_stack == 0) { + EMSG("Failed to allocate %u bytes\n", SECTION_SIZE); + EMSG(" of memory for user heap and stack\n"); + res = TEE_ERROR_OUT_OF_MEMORY; + goto error_return; + } + + } else if (ctx->num_res_funcs != 0) { + /* Unknown sub header */ + res = TEE_ERROR_BAD_FORMAT; + goto error_return; + } + + if ((ctx->flags & TA_FLAG_EXEC_DDR) != 0) { + /* + * Note that only User TA can be supported in DDR + * if executing in DDR, the size of the execution area + */ + size += + sizeof(ta_head_t) + ta->nbr_func * sizeof(ta_func_head_t) + + (ta->rel_dyn_got_size & TA_HEAD_GOT_MASK); + + ctx->mm = tee_mm_alloc(&tee_mm_sec_ddr, size); + + if (ctx->mm != NULL) { + /* cpy ddr TA into reserved memory space */ + struct tee_ta_param param = { 0 }; + void *dst; + + + res = tee_mmu_init(ctx); + if (res != TEE_SUCCESS) + goto error_return; + + res = tee_mmu_map(ctx, ¶m); + if (res != TEE_SUCCESS) { + EMSG("call tee_mmu_map_uta() failed %X", res); + goto error_return; + } + + tee_mmu_set_ctx(ctx); + + dst = (void *)tee_mmu_get_load_addr(ctx); + if (!tee_vbuf_is_non_sec(ta, size)) { + EMSG("User TA isn't in non-secure memory"); + res = TEE_ERROR_SECURITY; + goto error_return; + } + memcpy(dst, ta, size); + + core_cache_maintenance(DCACHE_AREA_CLEAN, dst, size); + core_cache_maintenance(ICACHE_AREA_INVALIDATE, dst, + size); + } + + } else { + size_t len = ctx->head->ro_size + ctx->head->rw_size; + + SMSG("no TA is currently supported in TEE RAM: abort."); + res = TEE_ERROR_NOT_SUPPORTED; + goto error_return; + + /* + * 'nmem' is normal world memory: saved read-only + * bytes of TA in pub DDR. They are protected by the related + * hashes saved in tee RAM. + */ + if (!tee_vbuf_is(TEE_MEM_NOT_RES_MMU_UL1, ctx->nmem, len)) { + tee_mm_entry_t *mm_nmem; + void *new_nmem; + /* + * At least parts the memory backing that paging of the + * TA resides in memory that will not be reachable when + * a User TA is loaded. + * + * Allocate TEE core phys DDR and copy TA to that + * instead. This is similar to what's done when making + * a kernel TA resident. + */ + + mm_nmem = tee_mm_alloc(&tee_mm_pub_ddr, len); + if (mm_nmem == NULL) { + EMSG("Out of pub DDR, cannot allocate %u", len); + res = TEE_ERROR_OUT_OF_MEMORY; + goto error_return; + } + new_nmem = (void *)tee_mm_get_smem(mm_nmem); + memcpy(new_nmem, ctx->nmem, len); + ctx->nmem = new_nmem; + } + ctx->mm = tee_mm_alloc(&tee_mm_vcore, size); + } + + if (ctx->mm == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto error_return; + } + + /* XXX is this used for a user TA in DDR? */ + ctx->smem_size = size; + + if ((ctx->flags & TA_FLAG_EXEC_DDR) == 0) { + /* + * HANDLE RW DATA + * Allocate data here and not in the abort handler to + * avoid running out of memory in abort mode. + */ + ctx->rw_data = + (uint32_t) (char *)malloc(ctx->head->zi_size + + ctx->head->rw_size); + if (ctx->rw_data == 0) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto error_return; + } + ctx->rw_data_usage = 0; + } + + if ((ctx->flags & TA_FLAG_EXEC_DDR) != 0) { + ctx->load_addr = tee_mmu_get_load_addr(ctx); + } else { + ctx->load_addr = + ((ctx->mm->offset << SMALL_PAGE_SHIFT) + TEE_PVMEM_LO) - + sizeof(ta_head_t) - + ctx->head->nbr_func * sizeof(ta_func_head_t); + } + + ctx->ref_count = 1; + + TAILQ_INSERT_TAIL(&tee_ctxes, ctx, link); + *ta_ctx = ctx; + /* + * Note that the setup below will cause at least one page fault so it's + * important that the session is fully registered at this stage. + */ + + /* Init rel.dyn, GOT, Service ptr, ZI and heap */ + tee_ta_init_reldyn(ctx); + tee_ta_init_got(ctx); + if ((ctx->flags & TA_FLAG_USER_MODE) != 0) + tee_ta_init_heap(ctx, heap_size); + else + tee_ta_init_serviceaddr(ctx); + tee_ta_init_zi(ctx); + + DMSG("Loaded TA at 0x%x, ro_size %u, rw_size %u, zi_size %u", + tee_mm_get_smem(ctx->mm), ctx->head->ro_size, + ctx->head->rw_size, ctx->head->zi_size); + DMSG("ELF load address 0x%x", ctx->load_addr); + + tee_mmu_set_ctx(NULL); + /* end thread protection (multi-threaded) */ + + return TEE_SUCCESS; + +error_return: + tee_mmu_set_ctx(NULL); + free(head); + free(ptr); + if (ctx != NULL) { + if ((ctx->flags & TA_FLAG_USER_MODE) != 0) + tee_mmu_final(ctx); + tee_mm_free(ctx->mm_heap_stack); + tee_mm_free(ctx->mm); + /* If pub DDR was allocated for nmem free it */ + tee_mm_free(tee_mm_find + (&tee_mm_pub_ddr, (uintptr_t) ctx->nmem)); + free(ctx); + } + return res; +} + +/* Maps kernal TA params */ +static TEE_Result tee_ta_param_pa2va(struct tee_ta_session *sess, + struct tee_ta_param *param) +{ + size_t n; + void *va; + + /* + * If kernel TA is called from another TA the mapping + * of that TA is borrowed and the addresses are already + * virtual. + */ + if (sess != NULL && sess->calling_sess != NULL) + return TEE_SUCCESS; + + for (n = 0; n < 4; n++) { + switch (TEE_PARAM_TYPE_GET(param->types, n)) { + case TEE_PARAM_TYPE_MEMREF_INPUT: + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + if (core_pa2va + ((uint32_t) param->params[n].memref.buffer, + (uint32_t *)&va)) + return TEE_ERROR_BAD_PARAMETERS; + param->params[n].memref.buffer = va; + break; + + default: + continue; + } + } + + return TEE_SUCCESS; +} + +/*----------------------------------------------------------------------------- + * Initialises a session based on the UUID or ptr to the ta + * Returns ptr to the session (ta_session) and a TEE_Result + *---------------------------------------------------------------------------*/ +static TEE_Result tee_ta_init_session(uint32_t *session_id, + struct tee_ta_session_head *open_sessions, + const TEE_UUID *uuid, + const kta_signed_header_t *signed_ta, + struct tee_ta_session **ta_session) +{ + TEE_Result res; + struct tee_ta_session *s; + + if (*session_id != 0) { + /* Session specified */ + res = tee_ta_verify_session_pointer((struct tee_ta_session *) + *session_id, open_sessions); + + if (res == TEE_SUCCESS) + *ta_session = (struct tee_ta_session *)*session_id; + + DMSG(" ... Re-open session => %p", (void *)*ta_session); + return res; + } + + if (uuid != NULL) { + /* Session not specified, find one based on uuid */ + struct tee_ta_ctx *ctx = NULL; + + ctx = tee_ta_context_find(uuid); + if (ctx == NULL) + goto load_ta; + + if ((ctx->flags & TA_FLAG_SINGLE_INSTANCE) == 0) + goto load_ta; + + if ((ctx->flags & TA_FLAG_MULTI_SESSION) == 0) + return TEE_ERROR_BUSY; + + DMSG(" ... Re-open TA %08lx-%04x-%04x", + ctx->head->uuid.timeLow, + ctx->head->uuid.timeMid, ctx->head->uuid.timeHiAndVersion); + + s = calloc(1, sizeof(struct tee_ta_session)); + if (s == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + ctx->ref_count++; + s->ctx = ctx; + s->cancel_mask = true; + *ta_session = s; + *session_id = (uint32_t) s; + TAILQ_INSERT_TAIL(open_sessions, s, link); + return TEE_SUCCESS; + } + +load_ta: + s = calloc(1, sizeof(struct tee_ta_session)); + if (s == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + res = TEE_ERROR_ITEM_NOT_FOUND; + if (signed_ta != NULL) { + DMSG(" Load dynamic TA"); + /* load and verify */ + res = tee_ta_load(signed_ta, &s->ctx); + } else if (uuid != NULL) { + DMSG(" Lookup for Static TA %08lx-%04x-%04x", + uuid->timeLow, uuid->timeMid, uuid->timeHiAndVersion); + /* Load Static TA */ + ta_static_head_t *ta; + for (ta = &__start_ta_head_section; + ta < &__stop_ta_head_section; ta++) { + if (memcmp(&ta->uuid, uuid, sizeof(TEE_UUID)) == 0) { + /* Load a new TA and create a session */ + DMSG(" Open %s", ta->name); + s->ctx = calloc(1, sizeof(struct tee_ta_ctx)); + if (s->ctx == NULL) { + free(s); + return TEE_ERROR_OUT_OF_MEMORY; + } + TAILQ_INIT(&s->ctx->open_sessions); + TAILQ_INIT(&s->ctx->cryp_states); + TAILQ_INIT(&s->ctx->objects); + s->ctx->num_res_funcs = 0; + s->ctx->ref_count = 1; + s->ctx->flags = TA_FLAG_MULTI_SESSION; + s->ctx->head = (ta_head_t *)ta; + s->ctx->static_ta = ta; + TAILQ_INSERT_TAIL(&tee_ctxes, s->ctx, link); + res = TEE_SUCCESS; + } + } + } + + if (res != TEE_SUCCESS) { + if (uuid != NULL) + EMSG(" ... Not found %08lx-%04x-%04x", + ((uuid) ? uuid->timeLow : 0xDEAD), + ((uuid) ? uuid->timeMid : 0xDEAD), + ((uuid) ? uuid->timeHiAndVersion : 0xDEAD)); + else + EMSG(" ... Not found"); + free(s); + return res; + } else + DMSG(" %s : %08lx-%04x-%04x", + s->ctx->static_ta ? s->ctx->static_ta->name : "dyn TA", + s->ctx->head->uuid.timeLow, + s->ctx->head->uuid.timeMid, + s->ctx->head->uuid.timeHiAndVersion); + + s->cancel_mask = true; + *ta_session = s; + *session_id = (uint32_t) s; + TAILQ_INSERT_TAIL(open_sessions, s, link); + + /* + * Call create_entry_point: for the static TA: to be cleaned. + * Here, we should call the TA "create" entry point, if TA supports + * it. Else, no TA code to call here. + * Note that this can be move to open_session in order static-TA and + * user-TA behaves the same + */ + if ((s->ctx->static_ta != NULL) && + (s->ctx->static_ta->create_entry_point != NULL)) { + DMSG(" Call create_entry_point"); + res = invoke_ta(s, 0, 0, COMMAND_CREATE_ENTRY_POINT); + if (res != TEE_SUCCESS) { + EMSG(" => (ret=%lx)", res); + tee_ta_close_session((uint32_t) s, open_sessions); + } + } + + return res; +} + +static void tee_ta_set_invoke_timeout(struct tee_ta_session *sess, + uint32_t cancel_req_to) +{ + TEE_Time current_time; + TEE_Time cancel_time = { UINT32_MAX, UINT32_MAX }; + + if (cancel_req_to == TEE_TIMEOUT_INFINITE) + goto out; + + if (tee_time_get_sys_time(¤t_time) != TEE_SUCCESS) + goto out; + + /* Check that it doesn't wrap */ + if (current_time.seconds + (cancel_req_to / 1000) >= + current_time.seconds) { + cancel_time.seconds = + current_time.seconds + cancel_req_to / 1000; + cancel_time.millis = current_time.millis + cancel_req_to % 1000; + if (cancel_time.millis > 1000) { + cancel_time.seconds++; + cancel_time.millis -= 1000; + } + } + +out: + sess->cancel_time = cancel_time; +} + +static TEE_Result tee_user_ta_enter(TEE_ErrorOrigin *err, + struct tee_ta_session *session, + enum tee_user_ta_func func, + uint32_t cancel_req_to, uint32_t cmd, + struct tee_ta_param *param) +{ + TEE_Result res; + TEE_Param *usr_params; + tee_paddr_t usr_stack; + tee_uaddr_t stack_uaddr; + tee_uaddr_t start_uaddr; + struct tee_ta_ctx *ctx = session->ctx; + ta_func_head_t *ta_func_head = + (ta_func_head_t *)((uint32_t) ctx->head + sizeof(ta_head_t)); + tee_uaddr_t params_uaddr; + TEE_ErrorOrigin serr = TEE_ORIGIN_TEE; + + TEE_ASSERT((ctx->flags & TA_FLAG_EXEC_DDR) != 0); + + TEE_ASSERT((uint32_t) func <= + (ctx->head->nbr_func - ctx->num_res_funcs)); + + /* Set timeout of entry */ + tee_ta_set_invoke_timeout(session, cancel_req_to); + + /* Map user space memory */ + res = tee_mmu_map(ctx, param); + if (res != TEE_SUCCESS) + goto cleanup_return; + + /* Switch to user ctx */ + tee_mmu_set_ctx(ctx); + + /* Make room for usr_params at top of stack */ + usr_stack = tee_mm_get_smem(ctx->mm_heap_stack) + ctx->stack_size; + usr_params = (TEE_Param *)usr_stack; + memcpy(usr_params, param->params, sizeof(param->params)); + usr_stack -= sizeof(param->params); + + res = tee_mmu_kernel_to_user(ctx, (tee_vaddr_t)usr_params, + ¶ms_uaddr); + if (res != TEE_SUCCESS) + goto cleanup_return; + + res = tee_mmu_kernel_to_user(ctx, usr_stack, &stack_uaddr); + if (res != TEE_SUCCESS) + goto cleanup_return; + + start_uaddr = ctx->load_addr + ta_func_head[func].start; + /* tee_thread_set_sess(session); */ + tee_rs = session; + + switch (func) { + case USER_TA_FUNC_OPEN_CLIENT_SESSION: + res = + tee_svc_enter_user_mode(param->types, params_uaddr, + (uint32_t) session, 0, stack_uaddr, + start_uaddr, &ctx->panicked, + &ctx->panic_code); + + /* + * According to GP spec the origin should allways be set to the + * TA after TA execution + */ + serr = TEE_ORIGIN_TRUSTED_APP; + break; + + case USER_TA_FUNC_CLOSE_CLIENT_SESSION: + res = tee_svc_enter_user_mode((uint32_t) session, 0, 0, 0, + stack_uaddr, start_uaddr, + &ctx->panicked, &ctx->panic_code); + + serr = TEE_ORIGIN_TRUSTED_APP; + break; + + case USER_TA_FUNC_INVOKE_COMMAND: + res = + tee_svc_enter_user_mode(cmd, param->types, params_uaddr, + (uint32_t) session, stack_uaddr, + start_uaddr, &ctx->panicked, + &ctx->panic_code); + + serr = TEE_ORIGIN_TRUSTED_APP; + break; + + default: + serr = TEE_ORIGIN_TEE; + res = TEE_ERROR_BAD_STATE; + } + + /* tee_thread_set_sess(NULL); */ + tee_rs = NULL; + + if (ctx->panicked) { + DMSG("tee_user_ta_enter: TA panicked with code 0x%x\n", + ctx->panic_code); + serr = TEE_ORIGIN_TEE; + res = TEE_ERROR_TARGET_DEAD; + } + + /* Copy out value results */ + memcpy(param->params, usr_params, sizeof(param->params)); + +cleanup_return: + /* Restore original ROM mapping */ + tee_mmu_set_ctx(NULL); + + /* + * Clear the cancel state now that the user TA has returned. The next + * time the TA will be invoked will be with a new operation and should + * not have an old cancellation pending. + */ + session->cancel = false; + + /* + * Can't update *err until now since it may point to an address + * mapped for the user mode TA. + */ + *err = serr; + + return res; +} + +/*----------------------------------------------------------------------------- + * Sets up virtual memory for the service + *---------------------------------------------------------------------------*/ +static TEE_Result tee_ta_func_execute(TEE_ErrorOrigin *err, + struct tee_ta_session *const session, + const uint32_t cmd, + struct tee_ta_param *param) +{ + TEE_Result res; + TEE_Result res2; + struct tee_ta_ctx *const ctx = session->ctx; + ta_func_head_t *ta_func_head = + (ta_func_head_t *)((uint32_t) ctx->head + sizeof(ta_head_t)); + uint32_t offset; + TEE_Operation op; + uint32_t n; + + res = tee_compat_param_new_to_old(param, &op); + if (res != TEE_SUCCESS) { + *err = TEE_ORIGIN_TEE; + return res; + } + + /* search for ta function */ + n = 0; + while (n < (ctx->head->nbr_func - ctx->num_res_funcs) && + cmd != ta_func_head->cmd_id) { + ta_func_head++; + n++; + } + if (cmd != ta_func_head->cmd_id) { + /* sevice not found */ + return TEE_ERROR_ITEM_NOT_FOUND; + } + + /* call service */ + offset = + ta_func_head->start - sizeof(ta_head_t) - + ctx->head->nbr_func * sizeof(ta_func_head_t) + + (ctx->mm->offset << SMALL_PAGE_SHIFT); + + tee_rs = session; + res = ((uint32_t(*)(TEE_Operation *)) + ((uint32_t) (TEE_PVMEM_LO + offset))) (&op); + tee_rs = NULL; + /* + * According to GP spec the origin should allways be set to the TA after + * TA execution + */ + *err = TEE_ORIGIN_TRUSTED_APP; + + res2 = tee_compat_param_old_to_new(&op, param); + if (res == TEE_SUCCESS && res2 != TEE_SUCCESS) { + *err = TEE_ORIGIN_TEE; + return res2; + } + + return res; +} + +/* + * Load a TA via RPC with UUID defined by input param uuid. The virtual + * address of the TA is recieved in out parameter ta + * + * Function is not thread safe + */ +TEE_Result tee_ta_rpc_load(const TEE_UUID *uuid, kta_signed_header_t **ta, + struct tee_ta_nwumap *map, uint32_t *ret_orig) +{ + TEE_Result res; + struct teesmc32_arg *arg; + struct teesmc32_param *params; + paddr_t pharg = 0; + paddr_t phpayload = 0; + paddr_t cookie = 0; + struct tee_rpc_load_ta_cmd *cmd_load_ta; + struct tee_ta_nwumap nwunmap; + + if (uuid == NULL || ta == NULL || ret_orig == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + /* get a rpc buffer */ + pharg = thread_rpc_alloc_arg(TEESMC32_GET_ARG_SIZE(2)); + thread_st_rpc_alloc_payload(sizeof(struct tee_rpc_load_ta_cmd), + &phpayload, &cookie); + if (!pharg || !phpayload) { + *ret_orig = TEE_ORIGIN_TEE; + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + if (!TEE_ALIGNMENT_IS_OK(pharg, struct teesmc32_arg) || + !TEE_ALIGNMENT_IS_OK(phpayload, struct tee_rpc_load_ta_cmd)) { + *ret_orig = TEE_ORIGIN_TEE; + res = TEE_ERROR_GENERIC; + goto out; + } + + if (core_pa2va(pharg, (uint32_t *)&arg) || + core_pa2va(phpayload, (uint32_t *)&cmd_load_ta)) { + *ret_orig = TEE_ORIGIN_TEE; + res = TEE_ERROR_GENERIC; + goto out; + } + + arg->cmd = TEE_RPC_LOAD_TA; + arg->num_params = 2; + /* Set a suitable error code in case our resquest is ignored. */ + arg->ret = TEE_ERROR_NOT_IMPLEMENTED; + params = TEESMC32_GET_PARAMS(arg); + params[0].attr = TEESMC_ATTR_TYPE_MEMREF_INOUT | + TEESMC_ATTR_CACHE_DEFAULT << TEESMC_ATTR_CACHE_SHIFT; + params[1].attr = TEESMC_ATTR_TYPE_MEMREF_OUTPUT | + TEESMC_ATTR_CACHE_DEFAULT << TEESMC_ATTR_CACHE_SHIFT; + + params[0].u.memref.buf_ptr = phpayload; + params[0].u.memref.size = sizeof(struct tee_rpc_load_ta_cmd); + params[1].u.memref.buf_ptr = 0; + params[1].u.memref.size = 0; + + memset(cmd_load_ta, 0, sizeof(struct tee_rpc_load_ta_cmd)); + memcpy(&cmd_load_ta->uuid, uuid, sizeof(TEE_UUID)); + + thread_rpc_cmd(pharg); + res = arg->ret; + + if (res != TEE_SUCCESS) { + *ret_orig = TEE_ORIGIN_COMMS; + goto out; + } + + nwunmap.ph = (paddr_t)cmd_load_ta->va; + nwunmap.size = params[1].u.memref.size; + if (core_pa2va(params[1].u.memref.buf_ptr, (uint32_t *)ta)) { + tee_ta_rpc_free(&nwunmap); + *ret_orig = TEE_ORIGIN_TEE; + res = TEE_ERROR_GENERIC; + goto out; + } + *map = nwunmap; + +out: + thread_rpc_free_arg(pharg); + thread_st_rpc_free_payload(cookie); + return res; +} + +static TEE_Result tee_ta_rpc_free(struct tee_ta_nwumap *map) +{ + TEE_Result res; + struct teesmc32_arg *arg; + struct teesmc32_param *params; + paddr_t pharg = 0; + + /* get a rpc buffer */ + pharg = thread_rpc_alloc_arg(TEESMC32_GET_ARG_SIZE(1)); + if (!pharg) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + if (!TEE_ALIGNMENT_IS_OK(pharg, struct teesmc32_arg)) { + res = TEE_ERROR_GENERIC; + goto out; + } + + if (core_pa2va(pharg, (uint32_t *)&arg)) { + res = TEE_ERROR_GENERIC; + goto out; + } + + arg->cmd = TEE_RPC_FREE_TA; + arg->num_params = 1; + /* Set a suitable error code in case our resquest is ignored. */ + arg->ret = TEE_ERROR_NOT_IMPLEMENTED; + params = TEESMC32_GET_PARAMS(arg); + params[0].attr = TEESMC_ATTR_TYPE_MEMREF_INPUT | + TEESMC_ATTR_CACHE_DEFAULT << TEESMC_ATTR_CACHE_SHIFT; + + params[0].u.memref.buf_ptr = map->ph; + params[0].u.memref.size = map->size; + + thread_rpc_cmd(pharg); + res = arg->ret; +out: + thread_rpc_free_arg(pharg); + return res; +} + +/*----------------------------------------------------------------------------- + * Close a Trusted Application and free available resources + *---------------------------------------------------------------------------*/ +TEE_Result tee_ta_close_session(uint32_t id, + struct tee_ta_session_head *open_sessions) +{ + struct tee_ta_session *sess, *next; + TEE_Result res = TEE_SUCCESS; + + DMSG("tee_ta_close_session(%x)", (unsigned int)id); + + if (id == 0) + return TEE_ERROR_ITEM_NOT_FOUND; + + TAILQ_FOREACH(sess, open_sessions, link) { + if (id == (uint32_t) sess) { + struct tee_ta_ctx *ctx = sess->ctx; + + DMSG(" ... Destroy session"); + + if (ctx->locked) + return TEE_ERROR_BUSY; + + if (ctx->busy) + return TEE_STE_ERROR_SYSTEM_BUSY; + ctx->busy = true; + + if ((ctx->static_ta != NULL) && + (ctx->static_ta->close_session_entry_point + != NULL) && + (!ctx->panicked)) { + DMSG(" ... close_session_entry_point"); + res = + invoke_ta(sess, 0, 0, + COMMAND_CLOSE_SESSION); + + } else if (((ctx->flags & TA_FLAG_USER_MODE) != 0) && + (!ctx->panicked)) { + TEE_ErrorOrigin err; + struct tee_ta_param param = { 0 }; + + tee_user_ta_enter( + &err, sess, + USER_TA_FUNC_CLOSE_CLIENT_SESSION, + TEE_TIMEOUT_INFINITE, 0, + ¶m); + } + + TAILQ_REMOVE(open_sessions, sess, link); + + ctx->busy = false; + + TEE_ASSERT(ctx->ref_count > 0); + ctx->ref_count--; + if (ctx->ref_count > 0) { + free(sess); + sess = NULL; + return TEE_SUCCESS; + } + + /* + * Clean all traces of the TA, both RO and RW data. + * No L2 cache maintenance to avoid sync problems + */ + if ((ctx->flags & TA_FLAG_EXEC_DDR) != 0) { + void *pa; + void *va; + uint32_t s; + + tee_mmu_set_ctx(ctx); + + if (ctx->mm != NULL) { + pa = (void *)tee_mm_get_smem(ctx->mm); + if (tee_mmu_user_pa2va(ctx, pa, &va) == + TEE_SUCCESS) { + s = tee_mm_get_bytes(ctx->mm); + memset(va, 0, s); + core_cache_maintenance + (DCACHE_AREA_CLEAN, va, s); + } + } + + if (ctx->mm_heap_stack != NULL) { + pa = (void *)tee_mm_get_smem + (ctx->mm_heap_stack); + if (tee_mmu_user_pa2va(ctx, pa, &va) == + TEE_SUCCESS) { + s = tee_mm_get_bytes + (ctx->mm_heap_stack); + memset(va, 0, s); + core_cache_maintenance + (DCACHE_AREA_CLEAN, va, s); + } + } + tee_mmu_set_ctx(NULL); + } + + DMSG(" ... Destroy TA ctx"); + + TAILQ_REMOVE(&tee_ctxes, ctx, link); + + /* + * Close sessions opened by this TA + * TAILQ_FOREACH() macro cannot be used as the element + * is removed inside tee_ta_close_session + */ + + for (struct tee_ta_session *linked_sess = + TAILQ_FIRST(&ctx->open_sessions); linked_sess; + linked_sess = next) { + next = linked_sess->link.tqe_next; + (void)tee_ta_close_session((uint32_t) + linked_sess, + &ctx->open_sessions); + } + + if ((ctx->static_ta != NULL) && + (ctx->static_ta->destroy_entry_point != NULL) && + (!ctx->panicked)) { + DMSG(" ... destroy_entry_point"); + res = + invoke_ta(sess, 0, 0, + COMMAND_DESTROY_ENTRY_POINT); + } + + free(sess); + sess = NULL; + + /* If TA was loaded in reserved DDR free the alloc. */ + tee_mm_free(tee_mm_find + (&tee_mm_pub_ddr, (uintptr_t) ctx->nmem)); + + if (ctx->nwumap.size != 0) + tee_ta_rpc_free(&ctx->nwumap); + + if ((ctx->flags & TA_FLAG_USER_MODE) != 0) { + tee_mmu_final(ctx); + tee_mm_free(ctx->mm_heap_stack); + } + if (ctx->static_ta == NULL) { + tee_mm_free(ctx->mm); + free((void *)ctx->rw_data); + free(ctx->head); + } + + /* Free cryp states created by this TA */ + tee_svc_cryp_free_states(ctx); + /* Close cryp objects opened by this TA */ + tee_obj_close_all(ctx); + /* Free emums created by this TA */ + tee_svc_storage_close_all_enum(ctx); + + free(ctx); + + return res; + } + } + + EMSG(" .... Session %p to removed is not found", (void *)sess); + return TEE_ERROR_ITEM_NOT_FOUND; +} + +TEE_Result tee_ta_make_current_session_resident(void) +{ + tee_mm_entry_t *mm; + void *addr; + size_t len; + struct tee_ta_ctx *ctx = tee_rs->ctx; + + /* + * Below reserved DDR is allocated for the backing memory of the TA + * and then the backing memory is copied to the new location and + * the pointer to normal world memory is updated. + */ + + if (tee_mm_addr_is_within_range(&tee_mm_pub_ddr, (uintptr_t) ctx->nmem)) + /* The backing pages are already in reserved DDR */ + goto func_ret; + + len = ctx->head->ro_size + ctx->head->rw_size; + mm = tee_mm_alloc(&tee_mm_pub_ddr, len); + if (mm == NULL) { + DMSG("Out of pub DDR, cannot allocate %u", len); + return TEE_ERROR_OUT_OF_MEMORY; + } + addr = (void *)tee_mm_get_smem(mm); + + memcpy(addr, ctx->nmem, len); + ctx->nmem = addr; + +func_ret: + ctx->locked = true; + return TEE_SUCCESS; +} + +void tee_ta_unlock_current_session(void) +{ + struct tee_ta_ctx *ctx = tee_rs->ctx; + + ctx->locked = false; +} + +static TEE_Result tee_ta_verify_param(struct tee_ta_session *sess, + struct tee_ta_param *param) +{ + tee_paddr_t p; + size_t l; + int n; + + for (n = 0; n < TEE_NUM_PARAMS; n++) { + switch (TEE_PARAM_TYPE_GET(param->types, n)) { + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + case TEE_PARAM_TYPE_MEMREF_INPUT: + + p = (tee_paddr_t)param->params[n].memref.buffer; + l = param->params[n].memref.size; + + if (core_pbuf_is(CORE_MEM_NSEC_SHM, p, l)) + break; + if ((sess->ctx->flags & TA_FLAG_UNSAFE_NW_PARAMS) && + core_pbuf_is(CORE_MEM_MULTPURPOSE, p, l)) + break; + if ((sess->clnt_id.login == TEE_LOGIN_TRUSTED_APP) && + core_pbuf_is(CORE_MEM_TA_RAM, p, l)) + break; + + return TEE_ERROR_SECURITY; + default: + break; + } + } + return TEE_SUCCESS; +} + +TEE_Result tee_ta_open_session(TEE_ErrorOrigin *err, + struct tee_ta_session **sess, + struct tee_ta_session_head *open_sessions, + const TEE_UUID *uuid, + const kta_signed_header_t *ta, + const TEE_Identity *clnt_id, + uint32_t cancel_req_to, + struct tee_ta_param *param) +{ + TEE_Result res; + uint32_t id = (uint32_t) *sess; + struct tee_ta_session *s = 0; + bool sess_inited = (*sess != NULL); + struct tee_ta_ctx *ctx; + + res = tee_ta_init_session(&id, open_sessions, uuid, ta, &s); + if (res != TEE_SUCCESS) { + EMSG("tee_ta_init_session() failed with error 0x%lx", res); + *err = TEE_ORIGIN_TEE; + return res; + } + + ctx = s->ctx; + ctx->nwumap.size = 0; + + if (ctx->panicked) { + EMSG("Calls tee_ta_close_session()"); + tee_ta_close_session(id, open_sessions); + *err = TEE_ORIGIN_TEE; + return TEE_ERROR_TARGET_DEAD; + } + + *sess = s; + /* Save idenity of the owner of the session */ + s->clnt_id = *clnt_id; + + /* + * Session context is ready. + */ + if (sess_inited) + goto out; + + if (((ctx->flags & TA_FLAG_USER_MODE) != 0 || ctx->static_ta != NULL) && + (!sess_inited)) { + /* Only User TA:s has a callback for open session */ + + res = tee_ta_verify_param(s, param); + if (res == TEE_SUCCESS) { + /* case the static TA */ + if ((ctx->static_ta != NULL) && + (ctx->static_ta->open_session_entry_point != NULL) + ) { + res = + invoke_ta(s, 0, param, + COMMAND_OPEN_SESSION); + + /* + * Clear the cancel state now that the user TA + * has returned. The next time the TA will be + * invoked will be with a new operation and + * should not have an old cancellation pending. + */ + s->cancel = false; + } else { + res = tee_user_ta_enter( + err, s, + USER_TA_FUNC_OPEN_CLIENT_SESSION, + cancel_req_to, 0, param); + } + } + + if (ctx->panicked || (res != TEE_SUCCESS)) + tee_ta_close_session(id, open_sessions); + } + +out: + /* + * Origin error equal to TEE_ORIGIN_TRUSTED_APP for "regular" error, + * apart from panicking. + */ + if (ctx->panicked) + *err = TEE_ORIGIN_TEE; + else + *err = TEE_ORIGIN_TRUSTED_APP; + + if (res != TEE_SUCCESS) + EMSG("Failed. Return error 0x%lx", res); + + return res; +} + +TEE_Result tee_ta_invoke_command(TEE_ErrorOrigin *err, + struct tee_ta_session *sess, + const TEE_Identity *clnt_id, + uint32_t cancel_req_to, uint32_t cmd, + struct tee_ta_param *param) +{ + TEE_Result res; + + if (sess->ctx->panicked) { + EMSG(" Panicked !"); + *err = TEE_ORIGIN_TEE; + OUTRMSG(TEE_ERROR_TARGET_DEAD); + } + + if (sess->ctx->busy) { + *err = TEE_ORIGIN_TEE; + return TEE_STE_ERROR_SYSTEM_BUSY; + } + sess->ctx->busy = true; + + res = tee_ta_verify_param(sess, param); + if (res != TEE_SUCCESS) { + *err = TEE_ORIGIN_TEE; + goto function_exit; + } + + if ((sess->ctx->static_ta != NULL) && + (sess->ctx->static_ta->invoke_command_entry_point != NULL)) { + res = tee_ta_param_pa2va(sess, param); + if (res != TEE_SUCCESS) { + *err = TEE_ORIGIN_TEE; + goto function_exit; + } + + /* Set timeout of entry */ + tee_ta_set_invoke_timeout(sess, cancel_req_to); + + DMSG(" invoke_command_entry_point(%p)", sess->user_ctx); + res = invoke_ta(sess, cmd, param, COMMAND_INVOKE_COMMAND); + + /* + * Clear the cancel state now that the user TA has returned. + * The next time the TA will be invoked will be with a new + * operation and should not have an old cancellation pending. + */ + sess->cancel = false; + + /* + * According to GP spec the origin should allways be set to the + * TA after TA execution + */ + *err = TEE_ORIGIN_TRUSTED_APP; + } else if ((sess->ctx->flags & TA_FLAG_USER_MODE) != 0) { + res = tee_user_ta_enter(err, sess, USER_TA_FUNC_INVOKE_COMMAND, + cancel_req_to, cmd, param); + } else { + res = tee_ta_param_pa2va(sess, param); + if (res != TEE_SUCCESS) { + *err = TEE_ORIGIN_TEE; + goto function_exit; + } + res = tee_ta_func_execute(err, sess, cmd, param); + } + + if (sess->ctx->panicked) { + *err = TEE_ORIGIN_TEE; + res = TEE_ERROR_TARGET_DEAD; + } + +function_exit: + sess->ctx->busy = false; + if (res != TEE_SUCCESS) + EMSG(" => Error: %lx of %ld\n", res, *err); + return res; +} + +TEE_Result tee_ta_cancel_command(TEE_ErrorOrigin *err, + struct tee_ta_session *sess, + const TEE_Identity *clnt_id) +{ + *err = TEE_ORIGIN_TEE; + + sess->cancel = true; + return TEE_SUCCESS; +} + +TEE_Result tee_ta_get_current_session(struct tee_ta_session **sess) +{ + if (tee_rs == NULL) + return TEE_ERROR_BAD_STATE; + *sess = tee_rs; + return TEE_SUCCESS; +} + +void tee_ta_set_current_session(struct tee_ta_session *sess) +{ + if (tee_rs != sess) { + struct tee_ta_ctx *ctx = NULL; + + if (sess != NULL) + ctx = sess->ctx; + + tee_rs = sess; + tee_mmu_set_ctx(ctx); + } +} + +TEE_Result tee_ta_get_client_id(TEE_Identity *id) +{ + TEE_Result res; + struct tee_ta_session *sess; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + if (id == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + *id = sess->clnt_id; + return TEE_SUCCESS; +} + +uintptr_t tee_ta_get_exec(const struct tee_ta_ctx *const ctx) +{ + if ((ctx->flags & TA_FLAG_EXEC_DDR) == 0) { + return tee_mm_get_smem(ctx->mm); + } else { + return tee_mmu_get_load_addr(ctx) + sizeof(ta_head_t) + + ctx->head->nbr_func * sizeof(ta_func_head_t); + } +} + +TEE_Result tee_ta_verify_session_pointer(struct tee_ta_session *sess, + struct tee_ta_session_head + *open_sessions) +{ + struct tee_ta_session *s; + + if (sess == (struct tee_ta_session *)TEE_SESSION_ID_STATIC_TA) + return TEE_SUCCESS; + + TAILQ_FOREACH(s, open_sessions, link) { + if (s == sess) + return TEE_SUCCESS; + } + return TEE_ERROR_BAD_PARAMETERS; +} diff --git a/core/arch/arm32/kernel/tee_time.c b/core/arch/arm32/kernel/tee_time.c new file mode 100644 index 00000000000..a98e8d4f309 --- /dev/null +++ b/core/arch/arm32/kernel/tee_time.c @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + + +#include +#include +#include +#include + +#include + +#include + +#define TEE_TIME_SHIFT 5 + +#define TEE_RTT0_HZ 32768UL + +#define TEE_RTT0_TICKS_PER_SECOND (TEE_RTT0_HZ) +#define TEE_RTT0_TICKS_PER_MINUTE (TEE_RTT0_TICKS_PER_SECOND * 60) +#define TEE_RTT0_TICKS_PER_HOUR (TEE_RTT0_TICKS_PER_MINUTE * 60) + +/* We'll receive one interrupt per hour */ +#define TEE_RTT0_WRAP_TICKS TEE_RTT0_TICKS_PER_HOUR + +#define TEE_RTT1_HZ 10UL +#define TEE_RTT1_WRAP_TICKS 0xffffffff + +/* + * Following is code example that could be used to activate time + * functionalities in TEE for arm32 + * +TEE_Result tee_time_init(void) +{ + - Disable timer and later change to 32kHz + IO(RTT0_CR) &= ~RTT_CR_EN; + + if (!(IO(RTT1_CR) & RTT_CR_EN)) { + IO(RTT1_IMSC) |= RTT_IMSC_IMSC; - disable interrupts + IO(RTT1_LR) = TEE_RTT1_WRAP_TICKS; - start the timer + + TEE_COMPILE_TIME_ASSERT(TEE_RTT1_HZ == TEE_TIME_BOOT_TICKS_HZ); + } + + return TEE_SUCCESS; +} + +uint32_t tee_time_get_boot_ticks(void) +{ + return TEE_RTT1_WRAP_TICKS - IO(RTT1_DR); +} + +uint32_t tee_time_get_boot_time_in_seconds(void) +{ + return tee_time_get_boot_ticks() / TEE_RTT1_HZ; +} +*/ + +static void tee_time_rtt0_init(void) +{ + static bool inited; /* initialized to false */ + + if (!inited) { + volatile uint32_t *cr = (uint32_t *)RTT0_CR; + volatile uint32_t *ctcr = (uint32_t *)RTT0_CTCR; + volatile uint32_t *lr = (uint32_t *)RTT0_LR; + volatile uint32_t *imsc = (uint32_t *)RTT0_IMSC; + + DMSG("tee_time_rtt0_init: First call may take a few secs"); + + /* + * Make sure timer is disabled. RTT_CR_EN is not accurate, + * enabling can be in progress too. Checking *ctcr takes + * care of that since updates to ctcr only propagates once + * timer really is disabled. + */ + while (*ctcr != 0 || (*cr & (RTT_CR_EN | RTT_CR_ENS)) != 0) { + *cr &= ~RTT_CR_EN; + *ctcr = 0; + } + + /* Change to 32kHz */ + *ctcr = 0; + + /* Enable interrupts on wrap */ + *imsc |= RTT_IMSC_IMSC; + + /* Start with the desired interrupt interval */ + *lr = TEE_RTT0_WRAP_TICKS; + + inited = true; + } +} + + +/* + * Following is code example that could be used to activate time + * functionalities in TEE for arm32 + * +TEE_Result tee_time_stamp(uint32_t *stamp) +{ + tee_time_rtt0_init(); + + *stamp = IO(RTT0_DR); + + return TEE_SUCCESS; +} + +TEE_Result tee_time_get(uint32_t stamp, uint32_t *time) +{ + TEE_Result res; + uint32_t val; + + res = tee_time_stamp(&val); + if (res != TEE_SUCCESS) + return res; + + *time = (stamp - val) >> TEE_TIME_SHIFT; + + return TEE_SUCCESS; +} + +TEE_Result tee_time_secure_rtc_update(const void *time, uint32_t time_size) +{ + return TEE_SUCCESS; +} + +TEE_Result tee_time_secure_rtc_update_check(bool *ok) +{ + *ok = true; + return TEE_SUCCESS; +} +*/ + +TEE_Result tee_time_get_sys_time(TEE_Time *time) +{ + uint32_t wrap0; + uint32_t wrap; + uint32_t timer; + + /* Stub system time support until a HW secure timer is supported */ + return tee_time_get_ree_time(time); + + tee_time_rtt0_init(); + + /* + * Reading wrap before and after we're reading DR to be able to + * detect if the timer wrapped while we where reading it. + */ + do { + wrap0 = tee_time_rtt0_wrap; + timer = TEE_RTT0_WRAP_TICKS - IO(RTT0_DR); + wrap = tee_time_rtt0_wrap; + } while (wrap0 != wrap); + + time->seconds = wrap * TEE_RTT0_WRAP_TICKS / TEE_RTT0_HZ + + timer / TEE_RTT0_HZ; + time->millis = + (timer % TEE_RTT0_HZ) / (TEE_RTT0_HZ / TEE_TIME_MILLIS_BASE); + + return TEE_SUCCESS; +} + +void tee_wait_specific(uint32_t milliseconds_delay) +{ + /* + * Any implementation must check it is secure, and robust to idle states + * of the arm + */ + /* usleep to be implemented */ + /* usleep(milliseconds_delay * 1000); */ +} diff --git a/core/arch/arm32/kernel/tee_time_unpg.c b/core/arch/arm32/kernel/tee_time_unpg.c new file mode 100644 index 00000000000..314532eef39 --- /dev/null +++ b/core/arch/arm32/kernel/tee_time_unpg.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +volatile uint32_t tee_time_rtt0_wrap; + +void tee_time_rtt_interrupt(void) +{ + if (IO(RTT0_MIS) & RTT_MIS_MIS) + tee_time_rtt0_wrap++; + + /* No need to clear the interrupt as ROM code is handling that. */ +} diff --git a/core/arch/arm32/kernel/thread.c b/core/arch/arm32/kernel/thread.c new file mode 100644 index 00000000000..b4daca961be --- /dev/null +++ b/core/arch/arm32/kernel/thread.c @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "thread_private.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static struct thread_ctx threads[NUM_THREADS]; + +static struct thread_core_local thread_core_local[CFG_TEE_CORE_NB_CORE]; + +thread_call_handler_t thread_stdcall_handler_ptr; +static thread_call_handler_t thread_fastcall_handler_ptr; +thread_fiq_handler_t thread_fiq_handler_ptr; +thread_svc_handler_t thread_svc_handler_ptr; +thread_abort_handler_t thread_abort_handler_ptr; + +static unsigned int thread_global_lock = UNLOCK; + +static void lock_global(void) +{ + cpu_spin_lock(&thread_global_lock); +} + +static void unlock_global(void) +{ + cpu_spin_unlock(&thread_global_lock); +} + +static struct thread_core_local *get_core_local(void) +{ + uint32_t cpu_id = get_core_pos(); + + /* + * IRQs must be disabled before playing with core_local since + * we otherwhise may be rescheduled to a different core in the + * middle of this function. + */ + assert(read_cpsr() & CPSR_I); + + assert(cpu_id < CFG_TEE_CORE_NB_CORE); + return &thread_core_local[cpu_id]; +} + +static bool have_one_active_thread(void) +{ + size_t n; + + for (n = 0; n < NUM_THREADS; n++) { + if (threads[n].state == THREAD_STATE_ACTIVE) + return true; + } + + return false; +} + +static void thread_alloc_and_run(struct thread_smc_args *args) +{ + size_t n; + struct thread_core_local *l = get_core_local(); + bool found_thread = false; + + assert(l->curr_thread == -1); + + lock_global(); + + if (!have_one_active_thread()) { + for (n = 0; n < NUM_THREADS; n++) { + if (threads[n].state == THREAD_STATE_FREE) { + threads[n].state = THREAD_STATE_ACTIVE; + found_thread = true; + break; + } + } + } + + unlock_global(); + + if (!found_thread) { + args->a0 = TEESMC_RETURN_EBUSY; + args->a1 = 0; + args->a2 = 0; + args->a3 = 0; + return; + } + + l->curr_thread = n; + + threads[n].regs.pc = (uint32_t)thread_stdcall_entry; + /* Stdcalls starts in SVC mode with masked IRQ and unmasked FIQ */ + threads[n].regs.cpsr = CPSR_MODE_SVC | CPSR_I; + threads[n].flags = 0; + /* Enable thumb mode if it's a thumb instruction */ + if (threads[n].regs.pc & 1) + threads[n].regs.cpsr |= CPSR_T; + /* Reinitialize stack pointer */ + threads[n].regs.svc_sp = threads[n].stack_va_end; + + /* + * Copy arguments into context. This will make the + * arguments appear in r0-r7 when thread is started. + */ + threads[n].regs.r0 = args->a0; + threads[n].regs.r1 = args->a1; + threads[n].regs.r2 = args->a2; + threads[n].regs.r3 = args->a3; + threads[n].regs.r4 = args->a4; + threads[n].regs.r5 = args->a5; + threads[n].regs.r6 = args->a6; + threads[n].regs.r7 = args->a7; + + /* Save Hypervisor Client ID */ + threads[n].hyp_clnt_id = args->a7; + + thread_resume(&threads[n].regs); +} + +static void thread_resume_from_rpc(struct thread_smc_args *args) +{ + size_t n = args->a3; /* thread id */ + struct thread_core_local *l = get_core_local(); + uint32_t rv = 0; + + assert(l->curr_thread == -1); + + lock_global(); + + if (have_one_active_thread()) { + rv = TEESMC_RETURN_EBUSY; + } else if (n < NUM_THREADS && + threads[n].state == THREAD_STATE_SUSPENDED && + args->a7 == threads[n].hyp_clnt_id) { + threads[n].state = THREAD_STATE_ACTIVE; + } else { + rv = TEESMC_RETURN_ERESUME; + } + + unlock_global(); + + if (rv) { + args->a0 = rv; + args->a1 = 0; + args->a2 = 0; + args->a3 = 0; + return; + } + + l->curr_thread = n; + + if (threads[n].have_user_map) + tee_mmu_set_map(&threads[n].user_map); + + /* + * Return from RPC to request service of an IRQ must not + * get parameters from non-secure world. + */ + if (threads[n].flags & THREAD_FLAGS_COPY_ARGS_ON_RETURN) { + /* + * Update returned values from RPC, values will appear in + * r0-r3 when thread is resumed. + */ + threads[n].regs.r0 = args->a0; + threads[n].regs.r1 = args->a1; + threads[n].regs.r2 = args->a2; + threads[n].regs.r3 = args->a3; + threads[n].flags &= ~THREAD_FLAGS_COPY_ARGS_ON_RETURN; + } + + thread_resume(&threads[n].regs); +} + +void thread_handle_smc_call(struct thread_smc_args *args) +{ + check_canaries(); + + if (TEESMC_IS_FAST_CALL(args->a0)) { + thread_fastcall_handler_ptr(args); + } else { + if (args->a0 == TEESMC32_CALL_RETURN_FROM_RPC) + thread_resume_from_rpc(args); + else + thread_alloc_and_run(args); + } +} + +void *thread_get_tmp_sp(void) +{ + struct thread_core_local *l = get_core_local(); + + return (void *)l->tmp_stack_va_end; +} + +void thread_state_free(void) +{ + struct thread_core_local *l = get_core_local(); + + assert(l->curr_thread != -1); + + lock_global(); + + assert(threads[l->curr_thread].state == THREAD_STATE_ACTIVE); + threads[l->curr_thread].state = THREAD_STATE_FREE; + threads[l->curr_thread].flags = 0; + l->curr_thread = -1; + + unlock_global(); +} + +int thread_state_suspend(uint32_t flags, uint32_t cpsr, uint32_t pc) +{ + struct thread_core_local *l = get_core_local(); + int ct = l->curr_thread; + + assert(ct != -1); + + check_canaries(); + + lock_global(); + + assert(threads[ct].state == THREAD_STATE_ACTIVE); + threads[ct].flags &= ~THREAD_FLAGS_COPY_ARGS_ON_RETURN; + threads[ct].flags |= flags & THREAD_FLAGS_COPY_ARGS_ON_RETURN; + threads[ct].regs.cpsr = cpsr; + threads[ct].regs.pc = pc; + threads[ct].state = THREAD_STATE_SUSPENDED; + + threads[ct].have_user_map = !tee_mmu_is_kernel_mapping(); + if (threads[ct].have_user_map) { + tee_mmu_get_map(&threads[ct].user_map); + tee_mmu_set_map(NULL); + } + + + l->curr_thread = -1; + + unlock_global(); + + return ct; +} + + +bool thread_init_stack(uint32_t thread_id, vaddr_t sp) +{ + switch (thread_id) { + case THREAD_TMP_STACK: { + struct thread_core_local *l = get_core_local(); + + l->tmp_stack_va_end = sp; + l->curr_thread = -1; + + thread_set_irq_sp(sp); + thread_set_fiq_sp(sp); + break; + } + + case THREAD_ABT_STACK: + thread_set_abt_sp(sp); + break; + + default: + if (thread_id >= NUM_THREADS) + return false; + if (threads[thread_id].state != THREAD_STATE_FREE) + return false; + + threads[thread_id].stack_va_end = sp; + } + + return true; +} + +void thread_init_handlers(const struct thread_handlers *handlers) +{ + thread_stdcall_handler_ptr = handlers->stdcall; + thread_fastcall_handler_ptr = handlers->fastcall; + thread_fiq_handler_ptr = handlers->fiq; + thread_svc_handler_ptr = handlers->svc; + thread_abort_handler_ptr = handlers->abort; + thread_init_vbar(); +} + +void thread_set_tsd(void *tsd, thread_tsd_free_t free_func) +{ + struct thread_core_local *l = get_core_local(); + + assert(l->curr_thread != -1); + assert(threads[l->curr_thread].state == THREAD_STATE_ACTIVE); + threads[l->curr_thread].tsd = tsd; + threads[l->curr_thread].tsd_free = free_func; +} + +void *thread_get_tsd(void) +{ + struct thread_core_local *l = get_core_local(); + int ct = l->curr_thread; + + if (ct == -1 || threads[ct].state != THREAD_STATE_ACTIVE) + return NULL; + else + return threads[ct].tsd; +} + +struct thread_ctx_regs *thread_get_ctx_regs(void) +{ + struct thread_core_local *l = get_core_local(); + + assert(l->curr_thread != -1); + return &threads[l->curr_thread].regs; +} + +void thread_set_irq(bool enable) +{ + struct thread_core_local *l; + uint32_t cpsr = read_cpsr(); + + /* get_core_local() requires IRQs to be disabled */ + write_cpsr(cpsr | CPSR_I); + + l = get_core_local(); + + assert(l->curr_thread != -1); + + if (enable) { + threads[l->curr_thread].flags |= THREAD_FLAGS_IRQ_ENABLE; + write_cpsr(cpsr & ~CPSR_I); + } else { + /* + * No need to disable IRQ here since it's already disabled + * above. + */ + threads[l->curr_thread].flags &= ~THREAD_FLAGS_IRQ_ENABLE; + } +} + +void thread_restore_irq(void) +{ + struct thread_core_local *l; + uint32_t cpsr = read_cpsr(); + + /* get_core_local() requires IRQs to be disabled */ + write_cpsr(cpsr | CPSR_I); + + l = get_core_local(); + + assert(l->curr_thread != -1); + + if (threads[l->curr_thread].flags & THREAD_FLAGS_IRQ_ENABLE) + write_cpsr(cpsr & ~CPSR_I); +} + +paddr_t thread_rpc_alloc_arg(size_t size) +{ + uint32_t rpc_args[THREAD_RPC_NUM_ARGS] = { + TEESMC_RETURN_RPC_ALLOC_ARG, size}; + + thread_rpc(rpc_args); + return rpc_args[1]; +} + +paddr_t thread_rpc_alloc_payload(size_t size) +{ + uint32_t rpc_args[THREAD_RPC_NUM_ARGS] = { + TEESMC_RETURN_RPC_ALLOC_PAYLOAD, size}; + + thread_rpc(rpc_args); + return rpc_args[1]; +} + +void thread_rpc_free_arg(paddr_t arg) +{ + if (arg) { + uint32_t rpc_args[THREAD_RPC_NUM_ARGS] = { + TEESMC_RETURN_RPC_FREE_ARG, arg}; + + thread_rpc(rpc_args); + } +} +void thread_rpc_free_payload(paddr_t payload) +{ + if (payload) { + uint32_t rpc_args[THREAD_RPC_NUM_ARGS] = { + TEESMC_RETURN_RPC_FREE_PAYLOAD, payload}; + + thread_rpc(rpc_args); + } +} + +void thread_rpc_cmd(paddr_t arg) +{ + uint32_t rpc_args[THREAD_RPC_NUM_ARGS] = {TEESMC_RETURN_RPC_CMD, arg}; + + thread_rpc(rpc_args); +} + +void thread_st_rpc_alloc_payload(size_t size, paddr_t *payload, paddr_t *cookie) +{ + uint32_t rpc_args[THREAD_RPC_NUM_ARGS] = { + TEESMC_RETURN_ST_RPC_ALLOC_PAYLOAD, size}; + + thread_rpc(rpc_args); + if (payload) + *payload = rpc_args[1]; + if (cookie) + *cookie = rpc_args[2]; +} + +void thread_st_rpc_free_payload(paddr_t cookie) +{ + uint32_t rpc_args[THREAD_RPC_NUM_ARGS] ={ + TEESMC_RETURN_ST_RPC_FREE_PAYLOAD, cookie}; + + thread_rpc(rpc_args); +} diff --git a/core/arch/arm32/kernel/thread_asm.S b/core/arch/arm32/kernel/thread_asm.S new file mode 100644 index 00000000000..2a988bf8b2a --- /dev/null +++ b/core/arch/arm32/kernel/thread_asm.S @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +FUNC thread_set_abt_sp , : + mrs r1, cpsr + cps #CPSR_MODE_ABT + mov sp, r0 + msr cpsr, r1 + bx lr +END_FUNC thread_set_abt_sp + +FUNC thread_set_irq_sp , : + mrs r1, cpsr + cps #CPSR_MODE_IRQ + mov sp, r0 + msr cpsr, r1 + bx lr +END_FUNC thread_set_irq_sp + + +FUNC thread_set_fiq_sp , : + mrs r1, cpsr + cps #CPSR_MODE_FIQ + mov sp, r0 + msr cpsr, r1 + bx lr +END_FUNC thread_set_irq_sp + +FUNC thread_recv_smc_call , : + ldr r9, =TEESMC32_CALL_HANDLE_FIQ + cmp r0, r9 + bne .recv_smc + /* + * FIQ raised while in non-secure world, unmask FIQ temporarily to + * receive the FIQ in as it's normally recieved when secure world + * is active when FIQ is raised. + */ + cpsie f + nop + nop + nop + nop /* We should have received IT by now... */ + cpsid f + mov r0, r1 + mov r1, r2 + mov r2, r3 + mov r3, r4 + b thread_issue_smc +.recv_smc: + push {r0-r7} + mov r0, sp + bl thread_handle_smc_call + /* + * Normally thread_handle_smc_call() should return via + * thread_exit(), thread_rpc(), but if thread_handle_smc_call() + * hasn't switched stack (fast call, FIQ, error detected) it will + * do a normal "C" return. + */ + pop {r0-r7} +thread_issue_smc: + smc #0 + b thread_recv_smc_call /* Next entry to secure world is here */ +END_FUNC thread_recv_smc_call + +/* void thread_resume(struct thread_ctx_regs *regs) */ +FUNC thread_resume , : + add r12, r0, #(13 * 4) /* Restore registers r0-r12 later */ + + cps #CPSR_MODE_SYS + ldm r12!, {r1, sp, lr} + msr spsr, r1 + +#ifdef THREAD_LOCAL_EXCEPTION_SPS + cps #CPSR_MODE_IRQ + ldm r12!, {r1, sp, lr} + msr spsr, r1 +#endif /*THREAD_LOCAL_EXCEPTION_SPS*/ + + cps #CPSR_MODE_SVC + ldm r12!, {r1, sp, lr} + msr spsr, r1 + +#ifdef THREAD_LOCAL_EXCEPTION_SPS + cps #CPSR_MODE_ABT + ldm r12!, {r1, sp, lr} + msr spsr, r1 + + cps #CPSR_MODE_UND + ldm r12!, {r1, sp, lr} + msr spsr, r1 +#endif /*THREAD_LOCAL_EXCEPTION_SPS*/ + + cps #CPSR_MODE_SVC + ldm r12, {r1, r2} + push {r1, r2} + + ldm r0, {r0-r12} + + + /* Restore CPSR and jump to the instruction to resume at */ + rfefd sp! +END_FUNC thread_resume + +/* + * Disables IRQ and FIQ and saves state of thread, returns original + * CPSR. + */ +LOCAL_FUNC thread_save_state , : + push {r12, lr} + /* + * Uses stack for temporary storage, while storing needed + * context in the thread context struct. + */ + + mrs r12, cpsr + + cpsid if /* Disable IRQ and FIQ */ + + push {r4-r7} + push {r0-r3} + + mov r5, r12 /* Save CPSR in a preserved register */ + mrs r6, cpsr /* Save current CPSR */ + + bl thread_get_ctx_regs + + pop {r1-r4} /* r0-r3 pushed above */ + stm r0!, {r1-r4} + pop {r1-r4} /* r4-r7 pushed above */ + stm r0!, {r1-r4} + stm r0!, {r8-r11} + + pop {r12, lr} + stm r0!, {r12} + + cps #CPSR_MODE_SYS + mrs r1, spsr + stm r0!, {r1, sp, lr} + +#ifdef THREAD_LOCAL_EXCEPTION_SPS + cps #CPSR_MODE_IRQ + mrs r1, spsr + stm r0!, {r1, sp, lr} +#endif /*THREAD_LOCAL_EXCEPTION_SPS*/ + + cps #CPSR_MODE_SVC + mrs r1, spsr + stm r0!, {r1, sp, lr} + +#ifdef THREAD_LOCAL_EXCEPTION_SPS + cps #CPSR_MODE_ABT + mrs r1, spsr + stm r0!, {r1, sp, lr} + + cps #CPSR_MODE_UND + mrs r1, spsr + stm r0!, {r1, sp, lr} +#endif /*THREAD_LOCAL_EXCEPTION_SPS*/ + + msr cpsr, r6 /* Restore mode */ + + mov r0, r5 /* Return original CPSR */ + bx lr +END_FUNC thread_save_state + +FUNC thread_stdcall_entry , : + /* Pass r0-r7 in a struct thread_smc_args */ + push {r0-r7} + mov r0, sp + ldr lr, =thread_stdcall_handler_ptr + ldr lr, [lr] + blx lr + /* + * Load the returned r0-r3 into preserved registers and skip the + * "returned" r4-r7 since they will not be returned to normal + * world. + */ + pop {r4-r7} + add sp, #(4 * 4) + + /* Disable interrupts before switching to temporary stack */ + cpsid if + bl thread_get_tmp_sp + mov sp, r0 + + bl thread_state_free + + mov r0, r4 + mov r1, r5 + mov r2, r6 + mov r3, r7 + b thread_issue_smc +END_FUNC thread_stdcall_entry + + +/* + * void thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]) + */ +FUNC thread_rpc , : + push {lr} + push {r0} + + bl thread_save_state + mov r4, r0 /* Save original CPSR */ + + /* + * Switch to temporary stack and SVC mode. Save CPSR to resume into. + */ + bl thread_get_tmp_sp + ldr r5, [sp] /* Get pointer to rv[] */ + cps #CPSR_MODE_SVC /* Change to SVC mode */ + mov sp, r0 /* Switch to tmp stack */ + + mov r0, #THREAD_FLAGS_COPY_ARGS_ON_RETURN + mov r1, r4 /* CPSR to restore */ + ldr r2, =.thread_rpc_return + bl thread_state_suspend + mov r3, r0 /* Supply thread index */ + ldm r5, {r0-r2} /* Load rv[] into r0-r2 */ + b thread_issue_smc + +.thread_rpc_return: + /* + * At this point has the stack pointer been restored to the value + * it had when thread_save_state() was called above. + * + * Jumps here from thread_resume above when RPC has returned. The + * IRQ and FIQ bits are restored to what they where when this + * function was originally entered. + */ + pop {r12} /* Get pointer to rv[] */ + stm r12, {r0-r2} /* Store r0-r2 into rv[] */ + pop {pc} +END_FUNC thread_rpc + +LOCAL_FUNC thread_fiq_handler , : + /* FIQ has a +4 offset for lr compared to preferred return address */ + sub lr, lr, #4 + push {r0-r12, lr} + bl check_canaries + ldr lr, =thread_fiq_handler_ptr + ldr lr, [lr] + blx lr + pop {r0-r12, lr} + movs pc, lr +END_FUNC thread_fiq_handler + +LOCAL_FUNC thread_irq_handler , : + /* + * IRQ mode is set up to use tmp stack so FIQ has to be + * disabled before touching the stack. We can also assign + * SVC sp from IRQ sp to get SVC mode into the state we + * need when doing the SMC below. + */ + cpsid f /* Disable FIQ also */ + sub lr, lr, #4 + push {lr} + push {r12} + + bl thread_save_state + + mov r0, #0 + mrs r1, spsr + pop {r12} + pop {r2} + blx thread_state_suspend + mov r3, r0 /* Supply thread index */ + + /* + * Switch to SVC mode and copy current stack pointer as it already + * is the tmp stack. + */ + mov r0, sp + cps #CPSR_MODE_SVC + mov sp, r0 + + ldr r0, =TEESMC_RETURN_RPC_IRQ + mov r1, #0 + mov r2, #0 + /* r3 is already filled in above */ + b thread_issue_smc +END_FUNC thread_irq_handler + +FUNC thread_init_vbar , : + /* Set vector (VBAR) */ + ldr r0, =thread_vect_table + write_vbar r0 + bx lr +END_FUNC thread_init_vbar + +LOCAL_FUNC thread_abort_handler , : +thread_abort_handler: +thread_und_handler: + /* + * Switch to abort mode to use that stack instead. + */ + cps #CPSR_MODE_ABT + sub lr, lr, #4 + push {r0-r3, ip, lr} + cps #CPSR_MODE_UND + mrs r0, spsr + cps #CPSR_MODE_ABT + push {r0, r1} + msr spsr, r0 /* In case some code reads spsr directly */ + mov r0, #THREAD_ABORT_UNDEF + b .thread_abort_generic + +thread_dabort_handler: + sub lr, lr, #8 + push {r0-r3, ip, lr} + mrs r0, spsr + push {r0, r1} + mov r0, #THREAD_ABORT_DATA + b .thread_abort_generic + +thread_pabort_handler: + sub lr, lr, #4 + push {r0-r3, ip, lr} + mrs r0, spsr + push {r0, r1} + mov r0, #THREAD_ABORT_PREFETCH + b .thread_abort_generic + +.thread_abort_generic: + mov r1, sp + ldr lr, =thread_abort_handler_ptr; + ldr lr, [lr] + blx lr + pop {r0, r1} + msr spsr, r0 + pop {r0-r3, ip, lr} + movs pc, lr +END_FUNC thread_abort_handler + +LOCAL_FUNC thread_svc_handler , : +/* + * TODO figure out an efficient way of redesigning tee_svc_syscall to allow + * usage of this code instead. + */ +#if 0 + push {r0-r5, lr} + mrs r0, spsr + push {r0} + mov r0, sp + ldr lr, =thread_svc_handler_ptr; + ldr lr, [lr] + blx lr + pop {r0} + msr spsr, r0 + pop {r0-r5, lr} + movs pc, lr +#else + ldr pc, =tee_svc_syscall +#endif +END_FUNC thread_svc_handler + + .align 5 +LOCAL_FUNC thread_vect_table , : + b . /* Reset */ + b thread_und_handler /* Undefined instruction */ + b thread_svc_handler /* System call */ + b thread_pabort_handler /* Prefetch abort */ + b thread_dabort_handler /* Data abort */ + b . /* Reserved */ + b thread_irq_handler /* IRQ */ + b thread_fiq_handler /* FIQ */ +END_FUNC thread_vect_table diff --git a/core/arch/arm32/kernel/thread_private.h b/core/arch/arm32/kernel/thread_private.h new file mode 100644 index 00000000000..9e6dfef265d --- /dev/null +++ b/core/arch/arm32/kernel/thread_private.h @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef THREAD_PRIVATE_H +#define THREAD_PRIVATE_H + +#include + +enum thread_state { + THREAD_STATE_FREE, + THREAD_STATE_SUSPENDED, + THREAD_STATE_ACTIVE, +}; + +struct thread_ctx_regs { + uint32_t r0; + uint32_t r1; + uint32_t r2; + uint32_t r3; + uint32_t r4; + uint32_t r5; + uint32_t r6; + uint32_t r7; + uint32_t r8; + uint32_t r9; + uint32_t r10; + uint32_t r11; + uint32_t r12; + uint32_t usr_spsr; + uint32_t usr_sp; + uint32_t usr_lr; +#ifdef THREAD_LOCAL_EXCEPTION_SPS + uint32_t irq_spsr; + uint32_t irq_sp; + uint32_t irq_lr; +#endif /*THREAD_LOCAL_EXCEPTION_SPS*/ + uint32_t svc_spsr; + uint32_t svc_sp; + uint32_t svc_lr; +#ifdef THREAD_LOCAL_EXCEPTION_SPS + uint32_t abt_spsr; + uint32_t abt_sp; + uint32_t abt_lr; + uint32_t und_spsr; + uint32_t und_sp; + uint32_t und_lr; +#endif /*THREAD_LOCAL_EXCEPTION_SPS*/ + uint32_t pc; + uint32_t cpsr; +}; + +struct thread_ctx { + enum thread_state state; + vaddr_t stack_va_end; + void *tsd; + thread_tsd_free_t tsd_free; + uint32_t hyp_clnt_id; + uint32_t flags; + struct thread_ctx_regs regs; + struct tee_mmu_mapping user_map; + bool have_user_map; +}; + +struct thread_core_local { + vaddr_t tmp_stack_va_end; + int curr_thread; +}; + + +/* + * Initializes VBAR for current CPU (called by thread_init_handlers() + */ +void thread_init_vbar(void); + +/* Handles a stdcall, r0-r7 holds the parameters */ +void thread_stdcall_entry(void); + +/* + * Resumes execution of currently active thread by restoring context and + * jumping to the instruction where to continue execution. + * + * Arguments supplied by non-secure world will be copied into the saved + * context of the current thread if THREAD_FLAGS_COPY_ARGS_ON_RETURN is set + * in the flags field in the thread context. + */ +void thread_resume(struct thread_ctx_regs *regs); + +/* + * Private functions made available for thread_asm.S + */ + +/* Returns the temp stack for current CPU */ +void *thread_get_tmp_sp(void); + +/* Handles an SMC call by disptaching to the correct handler */ +void thread_handle_smc_call(struct thread_smc_args *args); + +/* + * Marks the current thread as suspended. And updated the flags + * for the thread context (see thread resume for use of flags). + * Returns thread index of the thread that was suspended. + */ +int thread_state_suspend(uint32_t flags, uint32_t cpsr, uint32_t pc); + +/* + * Marks the current thread as free. + */ +void thread_state_free(void); + +/* Returns a pointer to the saved registers in current thread context. */ +struct thread_ctx_regs *thread_get_ctx_regs(void); + +/* Sets sp for abort mode */ +void thread_set_abt_sp(vaddr_t sp); + +/* Sets sp for irq mode */ +void thread_set_irq_sp(vaddr_t sp); + +/* Sets sp for fiq mode */ +void thread_set_fiq_sp(vaddr_t sp); + +extern thread_call_handler_t thread_stdcall_handler_ptr; + +/* + * Suspends current thread and temorarily exits to non-secure world. + * This function returns later when non-secure world returns. + * + * The purpose of this function is to request services from non-secure + * world. + */ +#define THREAD_RPC_NUM_ARGS 3 +void thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]); + +#endif /*THREAD_PRIVATE_H*/ diff --git a/core/arch/arm32/kernel/tz_proc.S b/core/arch/arm32/kernel/tz_proc.S new file mode 100644 index 00000000000..7794f336828 --- /dev/null +++ b/core/arch/arm32/kernel/tz_proc.S @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * ARMv7 core support routines + */ + +#include + +.global cpu_dsb +.global cpu_dmb +.global cpu_isb +.global cpu_wfe +.global cpu_sev +.global cpu_disable_its +.global cpu_enable_its +.global cpu_read_cpsr +.global cpu_write_cpsr +.global cpu_read_ttbr0 +.global cpu_write_ttbr0 +.global cpu_spin_lock +.global cpu_spin_trylock +.global cpu_spin_unlock +.global mmu_enable @ CeCh ADD +.global mmu_enable_icache @ CeCh ADD +.global mmu_enable_dcache @ CeCh ADD + +.section .text +.balign 4 +.code 32 + +/* void cpu_dmb(void); */ +cpu_dmb: + dmb + bx lr + +/* void cpu_dsb(void); */ +cpu_dsb: + dsb + bx lr + +/* void cpu_isb(void); */ +cpu_isb: + isb + bx lr + +/* void cpu_wfe(void); */ +cpu_wfe: + wfe + bx lr + +/* void cpu_sev(void); */ +cpu_sev: + sev + bx lr + +/* void cpu_disable_its(void) - disable local core interruptions */ +cpu_disable_its: + cpsid if + mov pc, lr + +/* void cpu_enable_its(void) - enable local core interruptions */ +cpu_enable_its: + cpsie if + mov pc, lr + +/* unsigned int cpu_read_cpsr(void) - return CPRS in R0 */ +cpu_read_cpsr: + MRS R0, CPSR + BX LR + +/* void cpu_write_cpsr(cpsr) - write R0 content to CPSR */ +cpu_write_cpsr: + MSR CPSR_cxsf, R0 + BX LR + +/* uint32_t cpu_read_ttbr0(void) - read CP15 TTBR0 */ +cpu_read_ttbr0: + mrc p15, 0, r0, c2, c0 ,0 + bx lr + +/* void cpu_write_ttbr0(uint32_t ttbr0) - write CP15 TTBR0 */ +cpu_write_ttbr0: + mcr p15, 0, r0, c2, c0 ,0 + bx lr + +/* void cpu_spin_lock(lock address) - lock mutex */ +cpu_spin_lock: + mov r2, #LOCK +_spinlock_loop: + ldrex r1, [r0] + cmp r1, #UNLOCK + wfene + bne _spinlock_loop + strex r1, r2, [r0] + cmp r1, #0 + wfene + bne _spinlock_loop + dmb + bx lr + +/* int cpu_spin_trylock(lock address) - return 0 on success */ +cpu_spin_trylock: + mov r2, #LOCK + mov r1, r0 +_trylock_loop: + ldrex r0, [r1] + cmp r0, #0 + bne _trylock_out + strex r0, r2, [r1] + cmp r0, #0 + bne _trylock_loop + dmb + bx lr +_trylock_out: + clrex + dmb + bx lr + +/* void cpu_spin_unlock(lock address) - unlock mutex */ +cpu_spin_unlock: + dmb + mov r1, #UNLOCK + str r1, [r0] + dsb + sev + bx lr + +/* + * void mmu_enable(void) - enable MMU + * + * TLBs are invalidated before MMU is enabled. + * An DSB and ISB insures MMUs is enabled before routine returns + */ +mmu_enable: + + MCR p15, 0, R0, c8, c7, 0 + + MRC p15, 0, R0, c1, c0, 0 + + ORR R0, R0, #CP15_CONTROL_M_MASK + MCR p15, 0, R0, c1, c0, 0 + + DSB + ISB + + MOV PC, LR + +/* void mmu_enable_icache(void) - enable instruction cache */ +mmu_enable_icache: + + MOV R1, #0 + MCR p15, 0, R1, c7, c5, 0 /* write to Cache operations register */ + + MOV R1, #0 + MCR p15, 0, R1, c7, c5, 6 /* write to Cache operations register */ + + MRC p15, 0, R1, c1, c0 , 0 /* read control reg */ + ORR R1, R1, #CP15_CONTROL_I_MASK /* set ICache enable bit */ + MCR p15, 0, R1, c1, c0 , 0 /* write control reg */ + + DSB + ISB + + MOV PC, LR + +/* void mmu_enable_dcache(void) - enable data cache */ +mmu_enable_dcache: + + PUSH {R4,LR} + + + MRC p15, 0, R1, c1, c0 , 0 /* read control reg */ + ORR R1, R1, #CP15_CONTROL_C_MASK /* set DCache enable bit */ + MCR p15, 0, R1, c1, c0 , 0 /* write control reg */ + + DSB + ISB + + POP {R4,PC} diff --git a/core/arch/arm32/kernel/tz_ssvce.S b/core/arch/arm32/kernel/tz_ssvce.S new file mode 100644 index 00000000000..981f06eaa45 --- /dev/null +++ b/core/arch/arm32/kernel/tz_ssvce.S @@ -0,0 +1,846 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * ARMv7 Secure Services library + */ + +/* + * Variable(s) + */ + +#include +#include + +/* tee inits/monitors services */ +.global ssvce_monitormutex +.global secure_get_cpu_id +.global secure_setstacks +.global secure_restorecontext +.global secure_savecontext +.global secure_savecontext_reenter +.global ssvce_topoftempstack + +/* mmu init */ +.global secure_mmu_init +.global secure_mmu_init_cpuN +.global secure_mmu_disable /* TODO: align with mmu_enable() */ + +/* TLB maintenance */ +.global secure_mmu_datatlbinvall +.global secure_mmu_unifiedtlbinvall +.global secure_mmu_unifiedtlbinvbymva +.global secure_mmu_unifiedtlbinv_curasid +.global secure_mmu_unifiedtlbinv_byasid + +/* cache maintenance */ +.global arm_cl1_d_cleanbysetway +.global arm_cl1_d_invbysetway +.global arm_cl1_d_cleaninvbysetway +.global arm_cl1_d_cleanbypa +.global arm_cl1_d_invbypa +.global arm_cl1_d_cleaninvbypa +.global arm_cl1_i_inv_all +.global arm_cl1_i_inv +.global arm_cl2_cleaninvbyway +.global arm_cl2_invbyway +.global arm_cl2_cleanbyway +.global arm_cl2_cleanbypa +.global arm_cl2_invbypa +.global arm_cl2_cleaninvbypa + +/* + * Get CPU id: macro for local call. + * export unsigned long secure_get_cpu_id(void). + */ +.macro GET_CPU_ID reg + MRC p15, 0, \reg, c0, c0, 5 @ ; read MPIDR + AND \reg, #0x3 @ ; Get CPU ID +.endm + +.code 32 +.section .text +.balign 4 + +secure_get_cpu_id: + GET_CPU_ID R0 + MOV PC, LR + + +/* + * Store TTBR0 base address for tee core and TAs. + * These are defined from scatter file and resolved during linkage. + * Currently all cores use the same MMU L1 tables (core and TAs). + * Maybe some day, each CPU will use its own MMU table. + */ +CORE0_TTBR0_ADDR: + .word SEC_MMU_TTB_FLD +CORE0_TA_TTBR0_ADDR: + .word SEC_TA_MMU_TTB_FLD + +/* + * secure_mmu_init - init MMU for primary cpu + */ +secure_mmu_init: + MRC p15, 0, r0, c1, c0, 0 @ store in r0 contain of SCTLR (system control register) from CP15 + BIC r0, r0, #0x00004 @ disable data cache. (BIC = bit clear) + BIC r0, r0, #0x01000 @ disable instruction cache. + MCR p15, 0, r0, c1, c0, 0 + + MOV r0, #0x05 @ domain 0: teecore, domain 1: TA + MCR p15, 0, r0, c3, c0, 0 + + /* load tee core default mapping */ + push {lr} + LDR r0, CORE0_TTBR0_ADDR + LDR r1, CORE0_TA_TTBR0_ADDR + BL core_init_mmu + pop {lr} + +/* + * Set Table Table Base Control Reg + * --------------------------------- + * 31:6 - SBZ + * 5 - PD[1], whether misses in TTBR1 causes a table walk + * 4 - PD[0], whether misses in TTBR0 causes a table walk + * 3 - SBZ + * 2:0 - N, split between TTBR0 and TTBR1 + */ + MOV r0,#0x0 @ N=0 => no TTBR1 used + MCR p15, 0, r0, c2, c0, 2 + + MOV PC, LR + +/* + * void secure_mmu_disable(void); + */ +secure_mmu_disable: + MRC p15, 0, R0, c1, c0, 0 + + BIC R0, R0, #CP15_CONTROL_M_MASK + MCR p15, 0, R0, c1, c0, 0 + + DSB + ISB + + MOV PC, LR + +.equ SEC_MMU_TTB_FLD_SN_SHM , 0x00011c02 @ 0x00011c0e to have memory cached + @ 0x00011c02 to have memory uncached + +.equ SEC_MMU_TTB_FLD_SN_DEV , 0x00001c02 @ device memory (iomem) + +/* @ ; r0 = base address (physical address) */ +/* @ ; Add a section of 1MBytes. */ +/* @ ; Base address r0 is aligned on 1MB */ +secure_mmu_addsection: + + MRC p15, 0, R1, c2, c0 ,0 /* Get TTBR0 location */ + + LSR R0, R0, #20 /* Clear bottom 20 bits, to find which 1MB block its in */ + LSL R2, R0, #2 /* Make a copy, and multiply by four. This gives offset into the page tables */ + LSL R0, R0, #20 /* Put back in address format */ + + LDR R3, =SEC_MMU_TTB_FLD_SN_SHM /* Descriptor template */ + ORR R0, R0, R3 /* Combine address and template */ + STR R0, [R1, R2] + + MOV PC, LR + +secure_mmu_addsectiondevice: + + MRC p15, 0, R1, c2, c0 ,0 /* Get TTBR0 location */ + + LSR R0, R0, #20 /* Clear bottom 20 bits, to find which 1MB block its in */ + LSL R2, R0, #2 /* Make a copy, and multiply by four. This gives offset into the page tables */ + LSL R0, R0, #20 /* Put back in address format */ + + LDR R3, =SEC_MMU_TTB_FLD_SN_DEV /* Descriptor template */ + ORR R0, R0, R3 /* Combine address and template */ + STR R0, [R1, R2] + + MOV PC, LR + +secure_mmu_removesection: + + MRC p15, 0, R1, c2, c0 ,0 /* Get TTBR0 location */ + + LSR R0, R0, #20 /* Clear bottom 20 bits, to find which 1MB block its in */ + LSL R2, R0, #2 /* Make a copy, and multiply by four. This gives offset into the page tables */ + LSL R0, R0, #20 /* Put back in address format */ + + MOV R3, #0 /* Descriptor template */ + ORR R0, R0, R3 /* Combine address and template */ + STR R0, [R1, R2] + + MOV PC, LR + +.equ SEC_MMU_TTB_FLD_PT_SHM , 0xbfed0001 @ Template descriptor + +.equ SEC_MMU_TTB_SLD_SP_SHM , 0x00000473 @ 0x0000047f to have memory cached + @ 0x00000433 to have memory strongly ordered + @ 0x00000473 to have memory uncached + +/* @ ; r0 = base address (physical address) */ +/* @ ; Add a section of 4KB. */ +/* @ ; Base address r0 is aligned on 4KB */ +secure_mmu_addsmallpage: + PUSH {R4, R5} + + LDR R1, =SEC_MMU_TTB_SLD + + MOVW R2, #0x0000 + MOVT R2, #0xFFF0 + + BIC R2, R0, R2 + + LSR R2, R2, #12 /* Clear bottom 12 bits, to find which 4KB block its in */ + LSL R2, R2, #2 /* Make a copy, and multiply by four. This gives offset into the page tables */ + + LDR R3, =SEC_MMU_TTB_SLD_SP_SHM /* Descriptor template */ + ORR R0, R0, R3 /* Combine address and template */ + STR R0, [R1, R2] + + LDR R5, =SEC_MMU_TTB_SLD + LDR R4, [R5] + + MRC p15, 0, R1, c2, c0 ,0 /* Get TTBR0 location */ + + LSR R0, R0, #20 /* Clear bottom 20 bits, to find which 1MB block its in */ + LSL R2, R0, #2 /* Make a copy, and multiply by four. This gives offset into the page tables */ + LSL R0, R0, #20 /* Put back in address format */ + + LDR R3, =SEC_MMU_TTB_FLD_PT_SHM /* Descriptor template */ + STR R3, [R1, R2] + + POP {R4, R5} + MOV PC, LR + +secure_mmu_removesmallpage: + + LDR R1, =SEC_MMU_TTB_SLD + + MOVW R2, #0x0000 + MOVT R2, #0xFFF0 + + BIC R2, R0, R2 + + LSR R2, R2, #12 /* Clear bottom 12 bits, to find which 4KB block its in */ + LSL R2, R2, #2 /* Make a copy, and multiply by four. This gives offset into the page tables */ + + MOV R3, #0 /* Descriptor template */ + ORR R0, R0, R3 /* Combine address and template */ + STR R0, [R1, R2] + + LDR R5, =SEC_MMU_TTB_SLD + LDR R4, [R5] + + MRC p15, 0, R1, c2, c0 ,0 /* Get TTBR0 location */ + + LSR R0, R0, #20 /* Clear bottom 20 bits, to find which 1MB block its in */ + LSL R2, R0, #2 /* Make a copy, and multiply by four. This gives offset into the page tables */ + LSL R0, R0, #20 /* Put back in address format */ + + LDR R3, =SEC_MMU_TTB_FLD_PT_SHM /* Descriptor template */ + STR R3, [R1, R2] + + MOV PC, LR + +/* + * - MMU maintenaince support --------------------------------------------- + */ + +/* + * void secure_mmu_datatlbinvall(void); + */ +secure_mmu_datatlbinvall: + + MCR p15, 0, R0, c8, c6, 0 + + DSB + ISB + + MOV PC, LR + +/* + * void secure_mmu_instrtlbinvall(void); + */ +secure_mmu_instrtlbinvall: + + MCR p15, 0, R0, c8, c5, 0 + + DSB + ISB + + MOV PC, LR + +/* + * void secure_mmu_unifiedtlbinvall(void); + */ +secure_mmu_unifiedtlbinvall: + + MCR p15, 0, R0, c8, c7, 0 + + DSB + ISB + + MOV PC, LR + +/* + * void secure_mmu_unifiedtlbinvbymva(mva); + * + * Combine VA and current ASID, and invalidate matching TLB + */ +secure_mmu_unifiedtlbinvbymva: + + b . @ Wrong code to force fix/check the routine before using it + + MRC p15, 0, R1, c13, c0, 1 /* Read CP15 Context ID Register (CONTEXTIDR) */ + ANDS R1, R1, #0xFF /* Get current ASID */ + ORR R1, R1, R0 /* Combine MVA and ASID */ + + MCR p15, 0, R1, c8, c7, 1 /* Invalidate Unified TLB entry by MVA */ + + DSB + ISB + + MOV PC, LR +/* + * void secure_mmu_unifiedtlbinv_curasid(void) + * + * Invalidate TLB matching current ASID + */ +secure_mmu_unifiedtlbinv_curasid: + + MRC p15, 0, R0, c13, c0, 1 /* Read CP15 Context ID Register (CONTEXTIDR) */ + AND R0, R0, #0xFF /* Get current ASID */ + MCR p15, 0, R0, c8, c7, 2 /* Invalidate Unified TLB entry by ASID */ + DSB + ISB + MOV PC, LR + +/* + * void secure_mmu_unifiedtlbinv_byasid(unsigned int asid) + * + * Invalidate TLB matching current ASID + */ +secure_mmu_unifiedtlbinv_byasid: + + AND R0, R0, #0xFF /* Get current ASID */ + MCR p15, 0, R0, c8, c7, 2 /* Invalidate Unified TLB entry by ASID */ + DSB + ISB + MOV PC, LR + +/* + * void arm_cl1_d_cleanbysetway(void) + */ +arm_cl1_d_cleanbysetway: + + MOV R0, #0 @ ; write the Cache Size selection register to be + MCR p15, 2, R0, c0, c0, 0 @ ; sure we address the data cache + ISB @ ; ISB to sync the change to the CacheSizeID reg + + MOV R0, #0 @ ; set way number to 0 +_cl_nextWay: + MOV R1, #0 @ ; set line number (=index) to 0 +_cl_nextLine: + ORR R2, R0, R1 @ ; construct way/index value + MCR p15, 0, R2, c7, c10, 2 @ ; DCCSW Clean data or unified cache line by set/way + ADD R1, R1, #1 << LINE_FIELD_OFFSET @ ; increment the index + CMP R1, #1 << LINE_FIELD_OVERFLOW @ ; look for overflow out of set field + BNE _cl_nextLine + ADD R0, R0, #1 << WAY_FIELD_OFFSET @ ; increment the way number + CMP R0, #0 @ ; look for overflow out of way field + BNE _cl_nextWay + + DSB @ ; synchronise + MOV PC, LR + +arm_cl1_d_invbysetway: + + MOV R0, #0 @ ; write the Cache Size selection register to be + MCR p15, 2, R0, c0, c0, 0 @ ; sure we address the data cache + ISB @ ; ISB to sync the change to the CacheSizeID reg + +_inv_dcache_off: + MOV R0, #0 @ ; set way number to 0 +_inv_nextWay: + MOV R1, #0 @ ; set line number (=index) to 0 +_inv_nextLine: + ORR R2, R0, R1 @ ; construct way/index value + MCR p15, 0, R2, c7, c6, 2 @ ; DCISW Invalidate data or unified cache line by set/way + ADD R1, R1, #1 << LINE_FIELD_OFFSET @ ; increment the index + CMP R1, #1 << LINE_FIELD_OVERFLOW @ ; look for overflow out of set field + BNE _inv_nextLine + ADD R0, R0, #1 << WAY_FIELD_OFFSET @ ; increment the way number + CMP R0, #0 @ ; look for overflow out of way field + BNE _inv_nextWay + + DSB @ ; synchronise + MOV PC, LR + +arm_cl1_d_cleaninvbysetway: + + MOV R0, #0 @ ; write the Cache Size selection register to be + MCR p15, 2, R0, c0, c0, 0 @ ; sure we address the data cache + ISB @ ; ISB to sync the change to the CacheSizeID reg + + MOV R0, #0 @ ; set way number to 0 +_cli_nextWay: + MOV R1, #0 @ ; set line number (=index) to 0 +_cli_nextLine: + ORR R2, R0, R1 @ ; construct way/index value + MCR p15, 0, R2, c7, c14, 2 @ ; DCCISW Clean and Invalidate data or unified cache line by set/way + ADD R1, R1, #1 << LINE_FIELD_OFFSET @ ; increment the index + CMP R1, #1 << LINE_FIELD_OVERFLOW @ ; look for overflow out of set field + BNE _cli_nextLine + ADD R0, R0, #1 << WAY_FIELD_OFFSET @ ; increment the way number + CMP R0, #0 @ ; look for overflow out of way field + BNE _cli_nextWay + + DSB @ ; synchronise + MOV PC, LR + +/* + * void arm_cl1_d_cleanbypa(unsigned long s, unsigned long e); + */ +arm_cl1_d_cleanbypa: + + CMP R0, R1 @ ; check that end >= start. Otherwise return. + BHI _cl_area_exit + + MOV R2, #0 @ ; write the Cache Size selection register to be + MCR p15, 2, R2, c0, c0, 0 @ ; sure we address the data cache + ISB @ ; ISB to sync the change to the CacheSizeID reg + + BIC R0, R0, #0x1F @ ; Mask 5 LSBits +_cl_area_nextLine: + MCR p15, 0, R0, c7, c10, 1 @ ; Clean data or unified cache line by MVA to PoC + ADD R0, R0, #1 << LINE_FIELD_OFFSET @ ; Next cache line + CMP R1, R0 + BPL _cl_area_nextLine + +_cl_area_exit: + + DSB @ ; synchronise + MOV PC, LR + +/* + * void arm_cl1_d_invbypa(unsigned long s, unsigned long e); + */ +arm_cl1_d_invbypa: + + CMP R0, R1 @ ; check that end >= start. Otherwise return. + BHI _inv_area_dcache_exit + + MOV R2, #0 @ ; write the Cache Size selection register to be + MCR p15, 2, R2, c0, c0, 0 @ ; sure we address the data cache + ISB @ ; ISB to sync the change to the CacheSizeID reg + +_inv_area_dcache_off: + BIC R0, R0, #0x1F @ ; Mask 5 LSBits +_inv_area_dcache_nl: + MCR p15, 0, R0, c7, c6, 1 @ ; Invalidate data or unified cache line by MVA to PoC + ADD R0, R0, #1 << LINE_FIELD_OFFSET @ ; Next cache line + CMP R1, R0 + BPL _inv_area_dcache_nl + +_inv_area_dcache_exit: + DSB + MOV PC, LR + +/* + * void arm_cl1_d_cleaninvbypa(unsigned long s, unsigned long e); + */ +arm_cl1_d_cleaninvbypa: + + CMP R0, R1 @ ; check that end >= start. Otherwise return. + BHI _cli_area_exit + + MOV R2, #0 @ ; write the Cache Size selection register to be + MCR p15, 2, R2, c0, c0, 0 @ ; sure we address the data cache + ISB @ ; ISB to sync the change to the CacheSizeID reg + + BIC R0, R0, #0x1F @ ; Mask 5 LSBits +_cli_area_nextLine: + MCR p15, 0, R0, c7, c14, 1 @ ; Clean and Invalidate data or unified cache line by MVA to PoC + ADD R0, R0, #1 << LINE_FIELD_OFFSET @ ; Next cache line + CMP R1, R0 + BPL _cli_area_nextLine + +_cli_area_exit: + DSB @ ; synchronise + MOV PC, LR + +/* + * void arm_cl1_i_inv_all( void ); + * + * Invalidates the whole instruction cache. + * It also invalidates the BTAC. + */ +arm_cl1_i_inv_all: + + /* Invalidate Entire Instruction Cache */ + MOV R0, #0 + MCR p15, 0, R0, c7, c5, 0 + DSB + + /* Flush entire branch target cache */ + MOV R1, #0 + MCR p15, 0, R1, c7, c5, 6 /* write to Cache operations register */ + + DSB /* ensure that maintenance operations are seen */ + ISB /* by the instructions rigth after the ISB */ + + BX LR + +/* + * void arm_cl1_i_inv(unsigned long start, unsigned long p_end); + * + * Invalidates instruction cache area whose (physical) limits are given in parameters. + * It also invalidates the BTAC. + */ +arm_cl1_i_inv: + + CMP R0, R1 /* Check that end >= start. Otherwise return. */ + BHI _inv_icache_exit + + BIC R0, R0, #0x1F /* Mask 5 LSBits */ +_inv_icache_nextLine: + MCR p15, 0, R0, c7, c5, 1 /* Invalidate ICache single entry (MVA) */ + ADD R0, R0, #1 << LINE_FIELD_OFFSET /* Next cache line */ + CMP R1, R0 + BPL _inv_icache_nextLine + DSB + + /* Flush entire branch target cache */ + MOV R1, #0 + MCR p15, 0, R1, c7, c5, 6 /* write to Cache operations register */ + DSB /* ensure that maintenance operations are seen */ + ISB /* by the instructions rigth after the ISB */ + +_inv_icache_exit: + BX LR + +/* + * void arm_cl2_cleaninvbyway(void) - clean & invalidate the whole L2 cache. + */ +arm_cl2_cleaninvbyway: + + /* Clean and invalidate all cache ways */ + movw r0, #0x27FC + movt r0, #0xFFFE + movw r1, #0x00FF + movt r1, #0x0000 + str r1, [r0] + + /* Wait for all cache ways to be cleaned and invalidated */ +loop_cli_way_done: + ldr r2, [r0] + and r2,r2,r1 + cmp r2, #0 + bne loop_cli_way_done + + /* Cache Sync */ + movw r0, #0x2730 + movt r0, #0xFFFE + + /* Wait for writing cache sync */ +loop_cli_sync: + ldr r1, [r0] + cmp r1, #0 + bne loop_cli_sync + + movw r1, #0x0001 + movt r1, #0x0000 + str r1, [r0] + +loop_cli_sync_done: + ldr r1, [r0] + cmp r1, #0 + bne loop_cli_sync_done + + mov pc, lr + +/* void (arm_cl2_invbyway(void) */ +arm_cl2_invbyway: + + /* Clean by Way */ + movw r0, #0x277C + movt r0, #0xFFFE + movw r1, #0x00FF /* assumes here 8-way L2 cache (orly) */ + movt r1, #0x0000 + str r1, [r0] + + /* Wait end of Invalidate by Way */ +loop_inv_way_done: + ldr r2, [r0] + and r2,r2,r1 + cmp r2, #0 + bne loop_inv_way_done + + /* Cache Sync */ + movw r0, #0x2730 + movt r0, #0xFFFE + + /* Wait for writing cache sync */ +loop_inv_way_sync: + ldr r1, [r0] + cmp r1, #0 + bne loop_inv_way_sync + + movw r1, #0x0001 + movt r1, #0x0000 + str r1, [r0] + + /* Wait end of Cache Sync */ +loop_inv_way_sync_done: + ldr r1, [r0] + cmp r1, #0 + bne loop_inv_way_sync_done + + mov pc, lr + +/* void arm_cl2_cleanbyway(u32 pa) */ +arm_cl2_cleanbyway: + + /* Clean by Way */ + movw r0, #0x27BC + movt r0, #0xFFFE + movw r1, #0x00FF + movt r1, #0x0000 + str r1, [r0] + + /* Wait end of Clean by Way */ +loop_cl_way_done: + ldr r2, [r0] + and r2,r2,r1 + cmp r2, #0 + bne loop_cl_way_done + + /* Cache Sync */ + movw r0, #0x2730 + movt r0, #0xFFFE + + /* Wait for writing cache sync */ +loop_cl_way_sync: + ldr r1, [r0] + cmp r1, #0 + bne loop_cl_way_sync + + movw r1, #0x0001 + movt r1, #0x0000 + str r1, [r0] + + /* Wait end of Cache Sync */ +loop_cl_way_sync_done: + ldr r1, [r0] + cmp r1, #0 + bne loop_cl_way_sync_done + + mov pc, lr + +/* + * void arm_cl2_cleanbypa(unsigned long start, unsigned long end); + * + * clean L2 cache by physical address range. + */ +arm_cl2_cleanbypa: + + /* + * ARM ERRATA #764369 + * Undocummented SCU Diagnostic Control Register + */ + MOVW R2, #0x0030 /* LSB */ + MOVT R2, #0xFFFE /* MSB */ + MOVW R3, #0x0001 + MOVT R3, #0x0000 + STR R3, [R2] + + DSB + /* + * ARM ERRATA #764369 + * Undocummented SCU Diagnostic Control Register + */ + + /* Clean PA */ +loop_cl2_clean_by_pa: + movw R2, #0x27B0 + movt R2, #0xFFFE + str R0, [R2] + + /* Wait for PA to be cleaned */ +loop_cl_pa_done: + ldr R3, [R2] + and R3,R3,R0 + cmp R3, #0 + bne loop_cl_pa_done + + add R0, R0, #32 + cmp R1, R0 + bne loop_cl2_clean_by_pa + + /* Cache Sync */ + movw R2, #0x2730 + movt R2, #0xFFFE + + /* Wait for writing cache sync */ +loop_cl_pa_sync: + ldr R0, [R2] + cmp R0, #0 + bne loop_cl_pa_sync + + movw R0, #0x0001 + movt R0, #0x0000 + str R0, [R2] + +loop_cl_pa_sync_done: + ldr R0, [R2] + cmp R0, #0 + bne loop_cl_pa_sync_done + + mov pc, lr + +/* + * void arm_cl2_invbypa(unsigned long start, unsigned long end); + * + * invalidate L2 cache by physical address range. + */ +arm_cl2_invbypa: + + /* + * ARM ERRATA #764369 + * Undocummented SCU Diagnostic Control Register + */ + MOVW R2, #0x0030 /* LSB */ + MOVT R2, #0xFFFE /* MSB */ + MOVW R3, #0x0001 + MOVT R3, #0x0000 + STR R3, [R2] + + DSB + /* + * ARM ERRATA #764369 + * Undocummented SCU Diagnostic Control Register + */ + + /* Invalidate PA */ +loop_cl2_inv_by_pa: + MOVW R2, #0x2770 + MOVT R2, #0xFFFE + STR R0, [R2] + + /* Wait for PA to be invalidated */ +loop_inv_pa_done: + LDR R3, [R2] + AND R3,R3,R0 + CMP R3, #0 + BNE loop_inv_pa_done + + ADD R0, R0, #32 + CMP R1, R0 + BNE loop_cl2_inv_by_pa + + + /* Cache Sync */ + MOVW R2, #0x2730 + MOVT R2, #0xFFFE + + /* Wait for writing cache sync */ +loop_inv_pa_sync: + LDR R0, [R2] + CMP R0, #0 + BNE loop_inv_pa_sync + + MOVW R0, #0x0001 + MOVT R0, #0x0000 + STR R0, [R2] + +loop_inv_pa_sync_done: + LDR R0, [R2] + CMP R0, #0 + BNE loop_inv_pa_sync_done + + MOV PC, LR + +/* + * void arm_cl2_cleaninvbypa(unsigned long start, unsigned long end); + * + * clean and invalidate L2 cache by physical address range. + */ +arm_cl2_cleaninvbypa: + + /* + * ARM ERRATA #764369 + * Undocummented SCU Diagnostic Control Register + */ + MOVW R0, #0x0030 /* LSB */ + MOVT R0, #0xFFFE /* MSB */ + MOVW R1, #0x0001 + MOVT R1, #0x0000 + STR R1, [R0] + + DSB + /* + * ARM ERRATA #764369 + * Undocummented SCU Diagnostic Control Register + */ + + /* Invalidate PA */ + movw r0, #0x27F0 + movt r0, #0xFFFE + mov r1, r12 // CeCh + str r1, [r0] + + /* Wait for PA to be invalidated */ +loop_cli_pa_done: + ldr r2, [r0] + and r2,r2,r1 + cmp r2, #0 + bne loop_cli_pa_done + + /* Cache Sync */ + movw r0, #0x2730 + movt r0, #0xFFFE + + /* Wait for writing cache sync */ +loop_cli_pa_sync: + ldr r1, [r0] + cmp r1, #0 + bne loop_cli_pa_sync + + movw r1, #0x0001 + movt r1, #0x0000 + str r1, [r0] + +loop_cli_pa_sync_done: + ldr r1, [r0] + cmp r1, #0 + bne loop_cli_pa_sync_done + + mov pc, lr diff --git a/core/arch/arm32/mm/core_mmu.c b/core/arch/arm32/mm/core_mmu.c new file mode 100644 index 00000000000..55133fbee0e --- /dev/null +++ b/core/arch/arm32/mm/core_mmu.c @@ -0,0 +1,622 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This core mmu supports static section mapping (1MByte). + * It should should finer mapping (4kByte coarse pages). + * It should also allow core to map/unmap (and va/pa) at run-time. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Default NSec shared memory allocated from NSec world */ +unsigned long default_nsec_shm_paddr; +unsigned long default_nsec_shm_size; + +/* platform handler for core_pbuf_is() */ +static unsigned long bootcfg_pbuf_is = 1; /* NOT is BSS */ +typedef bool(*platform_pbuf_is_t) (unsigned long attr, unsigned long paddr, + size_t size); + +/* + * WARNING: resources accessed during the initialization + * (sequence core_init_mmu()) are accessed *before* BSS is zero-initialised. + * Be careful NOT to load data that can be 'reset' to zero after + * core_init_mmu(), due to BSS init loop. + */ +static struct map_area *static_memory_map = (void *)1; /* not in BSS */ +static struct map_area *map_tee_ram = (void *)1; /* not in BSS */ +static struct map_area *map_ta_ram = (void *)1; /* not in BSS */ +static struct map_area *map_nsec_shm = (void *)1; /* not in BSS */ + +/* + * Save TTBR0 per CPU core running ARM-TZ. (Actually only 1 cpu run TEE) + * Save TTBR0 used for TA ampping (kTA or uTA). + * Currently not in BSS since BSS is init after MMU setup. + */ +static unsigned int core_ttbr0[CFG_TEE_CORE_NB_CORE] = { ~0, ~0 }; +static unsigned int coreta_ttbr0_pa[CFG_TEE_CORE_NB_CORE] = { ~0, ~0 }; +static unsigned int coreta_ttbr0_va[CFG_TEE_CORE_NB_CORE] = { ~0, ~0 }; + +/* bss is not init: def value must be non-zero */ +static bool memmap_notinit[CFG_TEE_CORE_NB_CORE] = { true, true }; + +#define MEMLAYOUT_NOT_INIT 1 +#define MEMLAYOUT_INIT 2 +static int memlayout_init = MEMLAYOUT_NOT_INIT; + +/* check if target buffer fits in a core default map area */ +static bool pbuf_inside_map_area(unsigned long p, size_t l, + struct map_area *map) +{ + if ((map->size == 0) || + (((uint32_t) p + l) < (uint32_t) p) || + ((uint32_t) p < map->pa) || + (((uint32_t) p + l) > (map->pa + map->size))) + return false; + return true; +} + +static struct map_area *find_map_by_va(void *va) +{ + struct map_area *map = static_memory_map; + unsigned long a = (unsigned long)va; + + while (map->type != MEM_AREA_NOTYPE) { + if ((a >= map->va) && (a < (map->va + map->size))) + return map; + map++; + } + return NULL; +} + +static struct map_area *find_map_by_pa(unsigned long pa) +{ + struct map_area *map = static_memory_map; + + while (map->type != MEM_AREA_NOTYPE) { + if ((pa >= map->pa) && (pa < (map->pa + map->size))) + return map; + map++; + } + return NULL; +} + +/* armv7 memory mapping attributes: section mapping */ +#define SECTION_SECURE (0 << 19) +#define SECTION_NOTSECURE (1 << 19) +#define SECTION_SHARED (1 << 16) +#define SECTION_NOTGLOBAL (1 << 17) +#define SECTION_RW ((0 << 15) | (1 << 10)) +#define SECTION_RO ((1 << 15) | (1 << 10)) +#define SECTION_TEXCB(tex, c, b) ((tex << 12) | (c << 3) | (b << 2)) +#define SECTION_DEVICE SECTION_TEXCB(0, 0, 1) +#define SECTION_NORMAL SECTION_TEXCB(1, 0, 0) +#define SECTION_NORMAL_CACHED SECTION_TEXCB(1, 1, 1) +#define SECTION_NO_EXEC (1 << 4) +#define SECTION_SECTION (2 << 0) +/* + * memarea_not_mapped - check memory not already (partially) mapped + * A finer mapping must be supported. Currently section mapping only! + */ +static bool memarea_not_mapped(struct map_area *map, void *ttbr0) +{ + uint32_t m, n; + + m = (map->pa >> 20) * 4; /* assumes pa=va */ + n = map->size >> 20; + while (n--) { + if (*((uint32_t *)((uint32_t)ttbr0 + m)) != 0) + return false; + m += 4; + } + return true; +} + +/* +* map_memarea - load mapping in target L1 table +* A finer mapping must be supported. Currently section mapping only! +*/ +static int map_memarea(struct map_area *map, void *ttbr0) +{ + uint32_t m, n; + unsigned long attr; + + /* + * invalid area confing + * - only section mapping currently supported + * - first section cannot be mapped (safety) + */ + if ((map == NULL) || + (ttbr0 == NULL) || + (map->va != 0) || + (map->region_size != 0) || + (map->pa == 0) || + ((map->pa + map->size - 1) < map->pa) || + (map->size == 0) || + (map->size & 0x000FFFFF) || + (map->pa & 0x000FFFFF) || (map->va & 0x000FFFFF)) { + while (1) + ; + return 1; + } + + attr = SECTION_SHARED | SECTION_NOTGLOBAL | SECTION_SECTION; + + if (map->device == true) + attr |= SECTION_DEVICE; + else if (map->cached == true) + attr |= SECTION_NORMAL_CACHED; + else + attr |= SECTION_NORMAL; + + if (map->rw == true) + attr |= SECTION_RW; + else + attr |= SECTION_RO; + + if (map->exec == false) + attr |= SECTION_NO_EXEC; + if (map->secure == false) + attr |= SECTION_NOTSECURE; + + map->va = map->pa; /* 1-to-1 pa=va mapping */ + map->region_size = 1 << 20; /* 1MB section mapping */ + + m = (map->pa >> 20) * 4; + n = map->size >> 20; + while (n--) { + *((uint32_t *)((uint32_t)ttbr0 + m)) = (m << 18) | attr; + m += 4; + } + + return 0; +} + +/* load_bootcfg_mapping - attempt to map the teecore static mapping */ +static void load_bootcfg_mapping(void *ttbr0) +{ + struct map_area *map, *in; + uint32_t *p, n; + + /* get memory bootcfg from system */ + in = bootcfg_get_memory(); + bootcfg_pbuf_is = (unsigned long)bootcfg_get_pbuf_is_handler(); + if (bootcfg_pbuf_is == 0) { + EMSG("invalid platform handler for pbuf_is"); + assert(0); + } + + /* we must find at least a PUB_RAM area and a TEE_RAM area */ + map_tee_ram = NULL; + map_ta_ram = NULL; + map_nsec_shm = NULL; + + /* reset L1 table */ + for (p = (uint32_t *)ttbr0, n = 4096; n > 0; n--) + *(p++) = 0; + + /* map what needs to be mapped (non-null size and non INTRAM/EXTRAM) */ + map = in; + while (map->type != MEM_AREA_NOTYPE) { + if (memarea_not_mapped(map, ttbr0) == false) { + EMSG("overlapping mapping ! trap CPU"); + assert(0); + } + + if (map_memarea(map, ttbr0)) { + EMSG("mapping failed ! trap CPU"); + assert(0); + } + + if (map->type == MEM_AREA_TEE_RAM) + map_tee_ram = map; + else if (map->type == MEM_AREA_TA_RAM) + map_ta_ram = map; + else if (map->type == MEM_AREA_NSEC_SHM) + map_nsec_shm = map; + + map++; + } + + if ((map_tee_ram == NULL) || (map_ta_ram == NULL) || + (map_nsec_shm == NULL)) { + EMSG("mapping area missing"); + assert(0); + } + + static_memory_map = in; +} + +/* + * core_init_mmu - init tee core default memory mapping + * + * location of target MMU L1 table is provided as argument. + * this routine sets the static default tee core mapping. + * + * If an error happend: core_init_mmu.c is expected to reset. + */ +unsigned int core_init_mmu(unsigned int ttbr0, unsigned int ta_ttbr0) +{ + uint32_t n; + + if (secure_get_cpu_id() >= CFG_TEE_CORE_NB_CORE) { + EMSG("invalid core ID %d. teecore supports %d cores.", + secure_get_cpu_id(), CFG_TEE_CORE_NB_CORE); + assert(0); + } + + if ((ttbr0 & TEE_MMU_TTBRX_ATTR_MASK) || + (ta_ttbr0 & TEE_MMU_TTBRX_ATTR_MASK)) { + EMSG("invalid MMU L1 addr: core=0x%X TA=0x%X", ttbr0, ta_ttbr0); + assert(0); + } + + if (memlayout_init == MEMLAYOUT_INIT) + goto skip_mmu_fill; + + /* Note that the initialization of the mmu may depend on the cutID */ + load_bootcfg_mapping((void *)ttbr0); + memlayout_init = MEMLAYOUT_INIT; + +skip_mmu_fill: + /* All CPUs currently use the same mapping, even on SMP */ + n = secure_get_cpu_id(); + ttbr0 |= TEE_MMU_DEFAULT_ATTRS; + core_ttbr0[n] = ttbr0; + cpu_write_ttbr0(ttbr0); + + memmap_notinit[n] = false; + + /* prepare TA mmu table handling */ + /* Support 1 TA MMU table location per CPU core must be implemented */ + if (core_pa2va(ta_ttbr0, (uint32_t *)&(coreta_ttbr0_va[n]))) { + EMSG("failed to get virtual address of ta_ttbr0 0x%X", + ta_ttbr0); + assert(0); + } + coreta_ttbr0_pa[n] = ta_ttbr0; + + return 0; +} + +/* return the tee core CP15 TTBR0 */ +uint32_t core_mmu_get_ttbr0(void) +{ + return core_ttbr0[secure_get_cpu_id()]; +} + +/* return the tee core mmu L1 table base address */ +uint32_t core_mmu_get_ttbr0_base(void) +{ + return core_mmu_get_ttbr0() & TEE_MMU_TTBRX_TTBX_MASK; +} + +/* return the tee core mmu L1 attributes */ +uint32_t core_mmu_get_ttbr0_attr(void) +{ + return core_mmu_get_ttbr0() & TEE_MMU_TTBRX_ATTR_MASK; +} + +/* return physical address of MMU L1 table of for TA mapping */ +uint32_t core_mmu_get_ta_ul1_pa(void) +{ + return coreta_ttbr0_pa[secure_get_cpu_id()]; +} + +/* return virtual address of MMU L1 table of for TA mapping */ +uint32_t core_mmu_get_ta_ul1_va(void) +{ + return coreta_ttbr0_va[secure_get_cpu_id()]; +} + +/* routines to retreive shared mem configuration */ +bool core_mmu_is_shm_cached(void) +{ + return map_nsec_shm ? map_nsec_shm->cached : false; +} + +/* + * test attributes of target physical buffer + * + * Flags: pbuf_is(SECURE, NOT_SECURE, RAM, IOMEM, KEYVAULT). + * + */ +bool core_pbuf_is(uint32_t attr, tee_paddr_t pbuf, size_t len) +{ + struct map_area *map; + + /* Empty buffers complies with anything */ + if (len == 0) + return true; + + switch (attr) { + case CORE_MEM_SEC: + return ((platform_pbuf_is_t) bootcfg_pbuf_is) (attr, pbuf, len); + case CORE_MEM_NON_SEC: + return ((platform_pbuf_is_t) bootcfg_pbuf_is) (attr, pbuf, len); + case CORE_MEM_TEE_RAM: + return pbuf_inside_map_area(pbuf, len, map_tee_ram); + case CORE_MEM_TA_RAM: + return pbuf_inside_map_area(pbuf, len, map_ta_ram); + case CORE_MEM_NSEC_SHM: + return pbuf_inside_map_area(pbuf, len, map_nsec_shm); + /* MultiPurpose and External RAM tests are platform specific */ + case CORE_MEM_MULTPURPOSE: + return ((platform_pbuf_is_t) bootcfg_pbuf_is) (attr, pbuf, len); + case CORE_MEM_EXTRAM: + return ((platform_pbuf_is_t) bootcfg_pbuf_is) (attr, pbuf, len); + case CORE_MEM_CACHED: + map = find_map_by_pa(pbuf); + if (map == NULL || !pbuf_inside_map_area(pbuf, len, map)) + return false; + return map->cached; + default: + return false; + } +} + +/* test attributes of target virtual buffer (in core mapping) */ +bool core_vbuf_is(uint32_t attr, const void *vbuf, size_t len) +{ + uint32_t p; + + /* Empty buffers complies with anything */ + if (len == 0) + return true; + + if (core_va2pa((uint32_t) vbuf, &p)) + return false; + + return core_pbuf_is(attr, (tee_paddr_t) p, len); +} + +/* + * Return true is MMU is initialized for current core + * Note that this is for DEBUG only, to help preventing + * use of pa2va va2pa before mmu table is setup ! + */ +static bool is_coremap_init(void) +{ + return !memmap_notinit[secure_get_cpu_id()]; +} + +/* core_va2pa - teecore exported service */ +int core_va2pa(uint32_t va, uint32_t *pa) +{ + struct map_area *map; + + if (!is_coremap_init()) + return -1; + + map = find_map_by_va((void *)va); + if (map == NULL) + return -1; + + *pa = (va & (map->region_size - 1)) | + ((map->pa + va - map->va) & ~(map->region_size - 1)); + return 0; +} + +/* core_pa2va - teecore exported service */ +int core_pa2va(uint32_t pa, uint32_t *va) +{ + struct map_area *map; + + if (!is_coremap_init()) + return -1; + + map = find_map_by_pa((unsigned long)pa); + if (map == NULL) + return -1; + + *va = (pa & (map->region_size - 1)) | + (((map->va + pa - map->pa)) & ~(map->region_size - 1)); + return 0; +} + +/* + * teecore gets some memory area definitions + */ +void core_mmu_get_mem_by_type(unsigned int type, unsigned int *s, + unsigned int *e) +{ + struct map_area *map; + + /* first scan the bootcfg memory layout */ + map = static_memory_map; + while (map->type != MEM_AREA_NOTYPE) { + if (map->type == type) { + *s = map->va; + *e = map->va + map->size; + return; + } + map++; + } + *s = 0; + *e = 0; +} + +int core_tlb_maintenance(int op, unsigned int a) +{ + switch (op) { + case TLBINV_DATATLB: + secure_mmu_datatlbinvall(); /* ??? */ + break; + case TLBINV_UNIFIEDTLB: + secure_mmu_unifiedtlbinvall(); + break; + case TLBINV_CURRENT_ASID: + secure_mmu_unifiedtlbinv_curasid(); + break; + case TLBINV_BY_ASID: + SMSG("TLBINV_BY_ASID is not yet supproted. Trap CPU!"); + while (1) + ; + secure_mmu_unifiedtlbinv_byasid(a); + break; + case TLBINV_BY_MVA: + SMSG("TLB_INV_SECURE_MVA is not yet supported!"); + while (1) + ; + secure_mmu_unifiedtlbinvbymva(a); + break; + default: + return 1; + } + return 0; +} + +static unsigned int cache_maintenance_l1(int op, void *start, size_t len) +{ + switch (op) { + case DCACHE_CLEAN: + arm_cl1_d_cleanbysetway(); + break; + case DCACHE_AREA_CLEAN: + arm_cl1_d_cleanbysetway(); + break; + case DCACHE_INVALIDATE: + arm_cl1_d_invbysetway(); + break; + case DCACHE_AREA_INVALIDATE: + arm_cl1_d_invbysetway(); + break; + case ICACHE_INVALIDATE: + arm_cl1_i_inv_all(); + break; + case ICACHE_AREA_INVALIDATE: + arm_cl1_i_inv_all(); + break; + case WRITE_BUFFER_DRAIN: + DMSG("unsupported operation 0x%X (WRITE_BUFFER_DRAIN)", + (unsigned int)op); + return -1; + case DCACHE_CLEAN_INV: + arm_cl1_d_cleaninvbysetway(); + break; + case DCACHE_AREA_CLEAN_INV: + arm_cl1_d_cleaninvbysetway(); + break; + default: + return TEE_ERROR_NOT_IMPLEMENTED; + } + return TEE_SUCCESS; + +} + +/* + * outer cahce maintenance mutex shared with NSec. + * + * At boot, teecore do not need a shared mutex with NSec. + * Once core has entered NSec state, teecore is not allowed to run outer cache + * maintenace sequence unless it has necogiate with NSec a shared mutex to + * spin lock on. + * + * In some situation (i.e boot, hibernation), teecore natively synchronise the + * cores and hence do not need to rely on NSec shared mutex. This can happend + * with NSec having previously negociated a shared mutex or not. Thus if + * teecore "disables" the outer (l2cc) shared mutex, it must be able to backup + * the registered one when enabling back the shared mutex. + * + * Currently no multi-cpu lock synchronisation: teecore runs execlusivley on + * 1 core at a given time. + */ +static unsigned int *l2cc_mutex; +static bool l2cc_mutex_required; /* default false */ + +void core_l2cc_mutex_set(void *mutex) +{ + l2cc_mutex = (unsigned int *)mutex; +} +void core_l2cc_mutex_activate(bool en) +{ + l2cc_mutex_required = en; +} + +static unsigned int cache_maintenance_l2(int op, void *start, size_t len) +{ + unsigned int ret; + + /* is shared mutex configured */ + if (l2cc_mutex_required && (l2cc_mutex == NULL)) + return TEE_ERROR_GENERIC; + if (l2cc_mutex_required) + cpu_spin_lock(l2cc_mutex); + + ret = TEE_SUCCESS; + switch (op) { + case L2CACHE_INVALIDATE: + arm_cl2_invbyway(); + break; + case L2CACHE_AREA_INVALIDATE: + arm_cl2_invbyway(); + break; + case L2CACHE_CLEAN: + arm_cl2_cleanbyway(); + break; + case L2CACHE_AREA_CLEAN: + arm_cl2_cleanbyway(); + break; + case L2CACHE_CLEAN_INV: + arm_cl2_cleaninvbyway(); + break; + case L2CACHE_AREA_CLEAN_INV: + arm_cl2_cleaninvbyway(); + break; + default: + ret = TEE_ERROR_NOT_IMPLEMENTED; + } + + if (l2cc_mutex_required) + cpu_spin_unlock(l2cc_mutex); + return ret; +} + +unsigned int core_cache_maintenance(int op, void *start, size_t len) +{ + unsigned int ret; + + ret = cache_maintenance_l1(op, start, len); + if (ret != TEE_ERROR_NOT_IMPLEMENTED) + return ret; + + ret = cache_maintenance_l2(op, start, len); + if (ret != TEE_ERROR_NOT_IMPLEMENTED) + return ret; + + EMSG("unsupported operation 0x%X", (unsigned int)op); + return TEE_ERROR_GENERIC; +} diff --git a/core/arch/arm32/mm/kta_table_unpg_asm.S b/core/arch/arm32/mm/kta_table_unpg_asm.S new file mode 100644 index 00000000000..e7ae339b00f --- /dev/null +++ b/core/arch/arm32/mm/kta_table_unpg_asm.S @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +.section .text + +.global translate_va2pa +.global invalidate_mmu_tlb + + .global WriteSCTLR + .global ReadSCTLR + .global WriteACTLR + .global ReadACTLR + .global WriteDIAGR + .global ReadDIAGR + + +.func translate_va2pa +translate_va2pa: + // R0 contains the original logical address + // Use privileged read VA to PA translation priviledges + MCR p15,0,R0,c7,c8,0 + ISB + + // Read the PAR value + MRC p15,0,R0,c7,c4,0 + ISB + + // return to caller + BX LR +.endfunc + + +.func invalidate_mmu_tlb +invalidate_mmu_tlb: + /* Invalidate entire Unified TLB Inner Sharable. Data R0 value ignored */ + MCR p15, 0, R0, c8, c3, 0 + + + // Ensure completion of the invalidate TBL operation + DSB + + // Ensure table changes visible to instruction fetch + ISB + + BX LR +.endfunc + +#ifdef __GRANT_RESTRICTED_ACCESS_SECURE_REGS + +/* __asm void WriteSCTLR(uint32_t regVal) */ + .func WriteSCTLR +WriteSCTLR: + MCR p15, 0, r0, c1, c0, 0 + BX LR + .endfunc + + +/* __asm uint32_t ReadSCTLR( void ) */ + .func ReadSCTLR +ReadSCTLR: + MRC p15, 0, r0, c1, c0, 0 + BX LR + .endfunc + +/* __asm void WriteACTLR(uint32_t regVal) */ + .func WriteACTLR +WriteACTLR: + MCR p15, 0, r0, c1, c0, 1 + BX LR + .endfunc + + +/* __asm uint32_t ReadACTLR( void ) */ + .func ReadACTLR +ReadACTLR: + MRC p15, 0, r0, c1, c0, 1 + BX LR + .endfunc + + +/* __asm void WriteDIAGR(uint32_t regVal) */ + .func WriteDIAGR +WriteDIAGR: + MCR p15, 0, r0, c15, c0, 1 + BX LR + .endfunc + +/* __asm uint32_t ReadDIAGR( void ) */ + .func ReadDIAGR +ReadDIAGR: + MRC p15, 0, r0, c15, c0, 1 + BX LR + .endfunc + +#endif + + +/*----------------------------------------------------------------------------- + GLOBAL VARIABLES + *---------------------------------------------------------------------------*/ diff --git a/core/arch/arm32/mm/sub.mk b/core/arch/arm32/mm/sub.mk new file mode 100644 index 00000000000..71f2dae03f9 --- /dev/null +++ b/core/arch/arm32/mm/sub.mk @@ -0,0 +1,20 @@ +srcs-y += core_mmu.c +cflags-core_mmu.c-y += -Wno-strict-aliasing -Wno-unused-parameter + +srcs-y += tee_pager_unpg.c +cflags-tee_pager_unpg.c-y += -Wno-unused-parameter + + +srcs-y += tee_mmu.c +cflags-tee_mmu.c-y += -Wno-unused-parameter + +srcs-y += kta_table_unpg_asm.S +srcs-y += tee_mm.c +cflags-tee_mm.c-y += -Wno-format +cflags-tee_mm.c-y += -Wno-format-nonliteral -Wno-format-security + +srcs-y += tee_mm_unpg.c +srcs-y += tee_mmu_unpg_asm.S +srcs-y += tee_mmu_unpg.c +srcs-y += tee_pager.c +srcs-y += tee_pager_unpg_asm.S diff --git a/core/arch/arm32/mm/tee_mm.c b/core/arch/arm32/mm/tee_mm.c new file mode 100644 index 00000000000..fcb8abfe5c8 --- /dev/null +++ b/core/arch/arm32/mm/tee_mm.c @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include + +bool tee_mm_init(tee_mm_pool_t *pool, uint32_t lo, uint32_t hi, uint8_t shift, + uint32_t flags) +{ + if (pool == NULL) + return false; + + pool->lo = lo; + pool->hi = hi; + pool->shift = shift; + pool->flags = flags; + pool->entry = calloc(1, sizeof(tee_mm_entry_t)); + + if (pool->entry == NULL) + return false; + + if (pool->flags & TEE_MM_POOL_HI_ALLOC) + pool->entry->offset = ((hi - lo - 1) >> shift) + 1; + pool->entry->pool = pool; + + return true; +} + +void tee_mm_final(tee_mm_pool_t *pool) +{ + if (pool == NULL || pool->entry == NULL) + return; + + while (pool->entry->next != NULL) + tee_mm_free(pool->entry->next); + free(pool->entry); + pool->entry = NULL; +} + +static tee_mm_entry_t *tee_mm_add(tee_mm_entry_t *p) +{ + /* add to list */ + if (p->next == NULL) { + p->next = malloc(sizeof(tee_mm_entry_t)); + if (p->next == NULL) + return NULL; + p->next->next = NULL; + } else { + tee_mm_entry_t *nn = malloc(sizeof(tee_mm_entry_t)); + if (nn == NULL) + return NULL; + nn->next = p->next; + p->next = nn; + } + return p->next; +} + +tee_mm_entry_t *tee_mm_alloc(tee_mm_pool_t *pool, uint32_t size) +{ + uint32_t psize; + tee_mm_entry_t *entry; + tee_mm_entry_t *nn; + + /* Check that pool is initialized */ + if (!pool || !pool->entry) + return NULL; + + entry = pool->entry; + if (size == 0) + psize = 0; + else + psize = ((size - 1) >> pool->shift) + 1; + /* Protect with mutex (multi thread) */ + + /* find free slot */ + if (pool->flags & TEE_MM_POOL_HI_ALLOC) { + while (entry->next != NULL && psize > + (entry->offset - entry->next->offset - + entry->next->size)) + entry = entry->next; + } else { + while (entry->next != NULL && psize > + (entry->next->offset - entry->size - entry->offset)) + entry = entry->next; + } + + /* check if we have enough memory */ + if (pool->flags & TEE_MM_POOL_HI_ALLOC) { + if (((entry->offset << pool->shift) - pool->lo) < size) + /* out of memory */ + return NULL; + } else { + if (((entry->offset << pool->shift) - pool->lo) < size) + /* out of memory */ + return NULL; + if ((((entry->offset + entry->size) << pool->shift) + size) >= + (pool->hi - pool->lo)) + /* out of memory */ + return NULL; + } + + nn = tee_mm_add(entry); + if (nn == NULL) + return NULL; + + if (pool->flags & TEE_MM_POOL_HI_ALLOC) + nn->offset = entry->offset - psize; + else + nn->offset = entry->offset + entry->size; + nn->size = psize; + nn->pool = pool; + + /* Protect with mutex end (multi thread) */ + + return nn; +} + +static inline bool fit_in_gap(tee_mm_pool_t *pool, tee_mm_entry_t *e, + uint32_t offslo, uint32_t offshi) +{ + if (pool->flags & TEE_MM_POOL_HI_ALLOC) { + if (offshi > e->offset || + (e->next != NULL && + (offslo < e->next->offset + e->next->size)) || + (offshi << pool->shift) - 1 > (pool->hi - pool->lo)) + /* memory not available */ + return false; + } else { + if (offslo < (e->offset + e->size) || + (e->next != NULL && (offshi > e->next->offset)) || + (offshi << pool->shift) > (pool->hi - pool->lo)) + /* memory not available */ + return false; + } + + return true; +} + +tee_mm_entry_t *tee_mm_alloc2(tee_mm_pool_t *pool, tee_vaddr_t base, + size_t size) +{ + tee_mm_entry_t *entry; + uint32_t offslo; + uint32_t offshi; + tee_mm_entry_t *mm; + + /* Check that pool is initialized */ + if (!pool || !pool->entry) + return NULL; + + /* Wrapping and sanity check */ + if ((base + size) < base || base < pool->lo) + return NULL; + + entry = pool->entry; + offslo = (base - pool->lo) >> pool->shift; + offshi = ((base - pool->lo + size - 1) >> pool->shift) + 1; + + /* find slot */ + if (pool->flags & TEE_MM_POOL_HI_ALLOC) { + while (entry->next != NULL && + offshi < entry->next->offset + entry->next->size) + entry = entry->next; + } else { + while (entry->next != NULL && offslo > entry->next->offset) + entry = entry->next; + } + + /* Check that memory is available */ + if (!fit_in_gap(pool, entry, offslo, offshi)) + return NULL; + + mm = tee_mm_add(entry); + if (mm == NULL) + return NULL; + + mm->offset = offslo; + mm->size = offshi - offslo; + mm->pool = pool; + + return mm; +} + +void tee_mm_free(tee_mm_entry_t *p) +{ + tee_mm_entry_t *entry; + + if (!p || !p->pool) + return; + + entry = p->pool->entry; + + /* Protect with mutex (multi thread) */ + + /* remove entry from list */ + while (entry->next != NULL && entry->next != p) + entry = entry->next; + + if (entry->next == NULL) { + DMSG("invalid mm_entry %p", p); + TEE_ASSERT(0); + } + entry->next = entry->next->next; + + if (p->pool->flags & TEE_MM_POOL_PAGED) { + /* unmap entry */ + tee_pager_unmap((uint32_t) (p->offset << p->pool->shift) + + p->pool->lo, p->size); + } + + free(p); + + /* Protect with mutex end (multi thread) */ +} + +size_t tee_mm_get_bytes(const tee_mm_entry_t *mm) +{ + if (!mm || !mm->pool) + return 0; + else + return mm->size << mm->pool->shift; +} + +bool tee_mm_addr_is_within_range(tee_mm_pool_t *pool, uint32_t addr) +{ + return (pool && ((addr >= pool->lo) && (addr <= pool->hi))); +} + +bool tee_mm_is_empty(tee_mm_pool_t *pool) +{ + return pool == NULL || pool->entry == NULL || pool->entry->next == NULL; +} diff --git a/core/arch/arm32/mm/tee_mm_unpg.c b/core/arch/arm32/mm/tee_mm_unpg.c new file mode 100644 index 00000000000..91f4416a31d --- /dev/null +++ b/core/arch/arm32/mm/tee_mm_unpg.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +/* Physical Public DDR pool */ +tee_mm_pool_t tee_mm_pub_ddr; + +/* Physical Secure DDR pool */ +tee_mm_pool_t tee_mm_sec_ddr; + +/* Virtual eSRAM pool */ +tee_mm_pool_t tee_mm_vcore; + +tee_mm_entry_t *tee_mm_find(const tee_mm_pool_t *pool, uint32_t addr) +{ + tee_mm_entry_t *entry = pool->entry; + uint16_t offset = (addr - pool->lo) >> pool->shift; + + if (addr > pool->hi || addr < pool->lo) + return NULL; + + while (entry->next != NULL) { + entry = entry->next; + + if ((offset >= entry->offset) && + (offset < (entry->offset + entry->size))) { + return entry; + } + } + + return NULL; +} + +uintptr_t tee_mm_get_smem(const tee_mm_entry_t *mm) +{ + return (mm->offset << mm->pool->shift) + mm->pool->lo; +} diff --git a/core/arch/arm32/mm/tee_mmu.c b/core/arch/arm32/mm/tee_mmu.c new file mode 100644 index 00000000000..ded29793c53 --- /dev/null +++ b/core/arch/arm32/mm/tee_mmu.c @@ -0,0 +1,897 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "tee_api_types.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#define TEE_MMU_PAGE_TEX_SHIFT 6 + +/* MMU table page flags */ +#define TEE_MMU_PAGE_NG (1 << 11) +#define TEE_MMU_PAGE_S (1 << 10) +#define TEE_MMU_PAGE_AP2 (1 << 9) +#define TEE_MMU_PAGE_TEX(x) (x << TEE_MMU_PAGE_TEX_SHIFT) +#define TEE_MMU_PAGE_AP1 (1 << 5) +#define TEE_MMU_PAGE_AP0 (1 << 4) +#define TEE_MMU_PAGE_C (1 << 3) +#define TEE_MMU_PAGE_B (1 << 2) +#define TEE_MMU_PAGE (1 << 1) +#define TEE_MMU_PAGE_XN (1 << 0) + +#define TEE_MMU_PAGE_CACHE_MASK \ + (TEE_MMU_PAGE_TEX(7) | TEE_MMU_PAGE_C | TEE_MMU_PAGE_B) + +#define TEE_MMU_PAGE_MASK ((1 << 12) - 1) + +/* For legacy */ +#define TEE_MMU_PAGE_LEGACY 0 + +/* MMU table section flags */ +#define TEE_MMU_SECTION_NS (1 << 19) +#define TEE_MMU_SECTION_NG (1 << 17) +#define TEE_MMU_SECTION_S (1 << 16) +#define TEE_MMU_SECTION_AP2 (1 << 15) +#define TEE_MMU_SECTION_TEX(x) (x << 12) +#define TEE_MMU_SECTION_AP1 (1 << 11) +#define TEE_MMU_SECTION_AP0 (1 << 10) +#define TEE_MMU_SECTION_DOMAIN(x) (x << 5) +#define TEE_MMU_SECTION_XN (1 << 4) +#define TEE_MMU_SECTION_C (1 << 3) +#define TEE_MMU_SECTION_B (1 << 2) +#define TEE_MMU_SECTION (1 << 1) + +/* User data, no cache attributes */ +#define TEE_MMU_SECTION_UDATA \ + (TEE_MMU_SECTION_NG | TEE_MMU_SECTION_S | \ + TEE_MMU_SECTION_AP1 | TEE_MMU_SECTION_AP0 | TEE_MMU_SECTION_XN |\ + TEE_MMU_SECTION_DOMAIN(1) | TEE_MMU_SECTION) + +/* User code, no cache attributes */ +#define TEE_MMU_SECTION_UCODE \ + (TEE_MMU_SECTION_NG | TEE_MMU_SECTION_S | \ + TEE_MMU_SECTION_AP1 | TEE_MMU_SECTION_AP0 | \ + TEE_MMU_SECTION_DOMAIN(1) | TEE_MMU_SECTION) + +/* Kernel data, global, privonly access, no exec, no cache attributes */ +#define TEE_MMU_SECTION_KDATA \ + (TEE_MMU_SECTION_S | \ + TEE_MMU_SECTION_AP0 | TEE_MMU_SECTION_XN | \ + TEE_MMU_SECTION_DOMAIN(1) | TEE_MMU_SECTION) + +/* Kernel data, global, privonly access, no exec, no cache attributes */ +#define TEE_MMU_SECTION_KCODE \ + (TEE_MMU_SECTION_S | \ + TEE_MMU_SECTION_AP0 | \ + TEE_MMU_SECTION_DOMAIN(1) | TEE_MMU_SECTION) + +/* Outer & Inner Write-Back, Write-Allocate. Default cache settings */ +#define TEE_MMU_SECTION_CACHEMASK \ + (TEE_MMU_SECTION_TEX(7) | TEE_MMU_SECTION_C | TEE_MMU_SECTION_B) +#define TEE_MMU_SECTION_OIWBWA \ + (TEE_MMU_SECTION_TEX(1) | TEE_MMU_SECTION_C | TEE_MMU_SECTION_B) +#define TEE_MMU_SECTION_NOCACHE \ + TEE_MMU_SECTION_TEX(1) + +#define TEE_MMU_KL2_ENTRY(page_num) \ + (*(uint32_t *)(SEC_VIRT_MMU_L2_BASE + ((uint32_t)(page_num)) * 4)) + +#define TEE_MMU_UL1_ENTRY(page_num) \ + (*(uint32_t *)(TEE_MMU_UL1_BASE + ((uint32_t)(page_num)) * 4)) + +/* Extract AP[2] and AP[1:0] */ +#define TEE_MMU_L1_AP(e) (((e >> 13) & 1) | ((e >> 10) & 3)) + +#define TEE_MMU_AP_USER_RO 0x02 +#define TEE_MMU_AP_USER_RW 0x03 + +/* Support for 31 concurrent sessions */ +static uint32_t g_asid = 0xffffffff; +static uint32_t g_current_context; + +static tee_mm_pool_t tee_mmu_virt_kmap; + +static uint32_t tee_mmu_get_io_size(const struct tee_ta_param *param) +{ + uint32_t i; + uint32_t res = 0; + + for (i = 0; i < 4; i++) { + uint32_t param_type = TEE_PARAM_TYPE_GET(param->types, i); + + if ((param_type == TEE_PARAM_TYPE_MEMREF_INPUT || + param_type == TEE_PARAM_TYPE_MEMREF_OUTPUT || + param_type == TEE_PARAM_TYPE_MEMREF_INOUT) && + param->params[i].memref.size != 0) { + res += + ((((uint32_t) param->params[i].memref. + buffer & SECTION_MASK) + + param->params[i].memref.size) >> SECTION_SHIFT) + + 1; + } + } + + return res; +} + +/* + * tee_mmu_is_mapped - Check if range defined by input params is mapped. + */ +static bool tee_mmu_is_mapped(const struct tee_ta_ctx *ctx, const uint32_t addr, + const uint32_t length, const uint32_t type) +{ + uint32_t i = 0; + uint32_t nbr_sections = (((addr & SECTION_MASK) + length) + >> SECTION_SHIFT) + 1; + bool ret = false; + + if (ctx == NULL || ctx->mmu == NULL || ctx->mmu->table == NULL || + ctx->mmu->size < ((addr + length) >> SECTION_SHIFT)) + return ret; + + while (i < ctx->mmu->size && !ret) { + if (addr > (ctx->mmu->table[i] & ~SECTION_MASK) && + addr < ((ctx->mmu->table[i] & ~SECTION_MASK) + + (1 << SECTION_SHIFT)) && + ((ctx->mmu->table[i] & SECTION_MASK) == type)) { + uint32_t section = 1; + while (section < nbr_sections) { + if ((ctx->mmu->table[i] >> SECTION_SHIFT) + + section != + (ctx->mmu-> + table[i + section] >> SECTION_SHIFT) || + ((ctx->mmu-> + table[i + section] & SECTION_MASK) != + type)) + break; + section++; + } + if (section == nbr_sections) + ret = true; + } + i++; + } + + return ret; +} + +TEE_Result tee_mmu_init(struct tee_ta_ctx *ctx) +{ + uint32_t asid = 1; + + if (ctx->context == 0) { + ctx->context = 1; + + /* Find available ASID */ + while (!(asid & g_asid) && (asid != 0)) { + ctx->context++; + asid = asid << 1; + } + + if (asid == 0) { + DMSG("Failed to allocate ASID"); + return TEE_ERROR_GENERIC; + } + g_asid &= ~asid; + } + + ctx->mmu = malloc(sizeof(tee_mmu_info_t)); + if (ctx->mmu) { + tee_mmu_info_t *p = ctx->mmu; + p->table = 0; + p->size = 0; + } else { + return TEE_ERROR_OUT_OF_MEMORY; + } + + return TEE_SUCCESS; +} + +static TEE_Result tee_mmu_map_io(struct tee_ta_ctx *ctx, uint32_t **buffer, + const uint32_t vio, struct tee_ta_param *param) +{ + uint32_t i; + uint32_t vi_offset = vio; + TEE_Result res = TEE_SUCCESS; + uint32_t nbr_sections, py_offset, v, section, sect_prot; + + /* Map IO buffers in public memory */ + for (i = 0; i < 4; i++) { + uint32_t param_type = TEE_PARAM_TYPE_GET(param->types, i); + TEE_Param *p = ¶m->params[i]; + + if ((!((param_type == TEE_PARAM_TYPE_MEMREF_INPUT) || + (param_type == TEE_PARAM_TYPE_MEMREF_OUTPUT) || + (param_type == TEE_PARAM_TYPE_MEMREF_INOUT))) || + (p->memref.size == 0)) + continue; + + nbr_sections = + ((((uint32_t) p->memref.buffer & SECTION_MASK) + + p->memref.size) >> SECTION_SHIFT) + 1; + py_offset = (uint32_t) p->memref.buffer >> SECTION_SHIFT; + v = ((vi_offset << SECTION_SHIFT) + + ((uint32_t) p->memref.buffer & SECTION_MASK)); + section = 0; + + if ((ctx->flags & TA_FLAG_USER_MODE) == + TA_FLAG_USER_MODE) { + sect_prot = TEE_MMU_SECTION_UDATA; + } else { + sect_prot = TEE_MMU_SECTION_KDATA; + } +#ifdef PAGER_DEBUG_PRINT + DMSG("tee_mmu_map: i 0x%x ph %p -> v %p\n nbr_sections %u", i, + p->memref.buffer, v, nbr_sections); +#endif + /* Set NS bit if buffer is not secure */ + if (tee_pbuf_is_non_sec + (p->memref.buffer, p->memref.size) == true) { + sect_prot |= TEE_MMU_SECTION_NS; + } else { + /* + * If secure, check here if security level is + * reached. This operation is likely to be + * platform dependent. + */ + + /* case STTEE on Orly2: it has to be TEE external DDR */ + if (core_pbuf_is(CORE_MEM_EXTRAM, + (tee_paddr_t) p->memref.buffer, + p->memref.size) == false) + return TEE_ERROR_SECURITY; + } + + /* + * Configure inner and outer cache settings. + */ + sect_prot &= ~TEE_MMU_SECTION_CACHEMASK; + sect_prot |= TEE_MMU_SECTION_TEX(4); + if (param->param_attr[i] & TEESMC_ATTR_CACHE_O_WRITE_THR) + sect_prot |= TEE_MMU_SECTION_TEX(2); + if (param->param_attr[i] & TEESMC_ATTR_CACHE_I_WRITE_BACK) + sect_prot |= TEE_MMU_SECTION_TEX(1); + if (param->param_attr[i] & TEESMC_ATTR_CACHE_O_WRITE_THR) + sect_prot |= TEE_MMU_SECTION_C; + if (param->param_attr[i] & TEESMC_ATTR_CACHE_O_WRITE_BACK) + sect_prot |= TEE_MMU_SECTION_B; + + if (((sect_prot & TEE_MMU_SECTION_NS) == TEE_MMU_SECTION_NS) && + ((sect_prot & TEE_MMU_SECTION_XN) == 0)) { + EMSG("invalid map config: nsec mem map as executable!"); + sect_prot |= TEE_MMU_SECTION_XN; + } + + if (tee_mmu_is_mapped(ctx, (uint32_t) p->memref.buffer, + p->memref.size, sect_prot)) { + res = tee_mmu_user_pa2va(ctx, p->memref.buffer, + &p->memref.buffer); + if (res != TEE_SUCCESS) + return res; + } else { + p->memref.buffer = (void *)v; + + while (section < nbr_sections) { + **buffer = + ((section + py_offset) << SECTION_SHIFT) | + sect_prot; + (*buffer)++; + section++; + } + + vi_offset += nbr_sections; + } + } + + return res; +} + +/* + * tee_mmu_map - alloc and fill mmu mapping table for a user TA (uTA). + * + * param - Contains the physical addr of the input buffers + * Returns logical addresses + * + * Allocate a table to store the N first section entries of the MMU L1 table + * used to map the target user TA, and clear table to 0. + * Load mapping for the TA stack_heap area, code area and params area (params + * are the 4 GP TEE TA invoke parameters buffer). + */ +TEE_Result tee_mmu_map(struct tee_ta_ctx *ctx, struct tee_ta_param *param) +{ + TEE_Result res = TEE_SUCCESS; + uint32_t py_offset; + void *p; + uintptr_t smem; + uint32_t *buffer; + uint32_t section = 0, section_cnt = 0; + + TEE_ASSERT((ctx->flags & TA_FLAG_EXEC_DDR) != 0); + + ctx->mmu->size = tee_mm_get_size(ctx->mm_heap_stack) + + tee_mm_get_size(ctx->mm) + tee_mmu_get_io_size(param) + + TEE_DDR_VLOFFSET; + + if (ctx->mmu->size > TEE_MMU_UL1_NUM_USER_ENTRIES) { + res = TEE_ERROR_EXCESS_DATA; + goto exit; + } + + if (ctx->mmu->table) + free(ctx->mmu->table); + + ctx->mmu->table = malloc(ctx->mmu->size * 4); + if (ctx->mmu->table == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto exit; + } + memset(ctx->mmu->table, 0, ctx->mmu->size * 4); + + /* + * Map heap and stack + */ + smem = tee_mm_get_smem(ctx->mm_heap_stack); + if (core_va2pa((uint32_t)smem, (uint32_t *)&p)) { + res = TEE_ERROR_SECURITY; + goto exit; + } + + py_offset = (uint32_t)p >> SECTION_SHIFT; + + buffer = (uint32_t *)ctx->mmu->table + TEE_DDR_VLOFFSET; + while (section < tee_mm_get_size(ctx->mm_heap_stack)) { + *buffer++ = ((section++ + py_offset) << SECTION_SHIFT) | + TEE_MMU_SECTION_UDATA | TEE_MMU_SECTION_OIWBWA; + section_cnt++; + } + + /* + * Map code + */ + smem = tee_mm_get_smem(ctx->mm); + if (core_va2pa((uint32_t)smem, (uint32_t *)&p)) { + res = TEE_ERROR_SECURITY; + goto exit; + } + + py_offset = (uint32_t) p >> SECTION_SHIFT; + + section = 0; + while (section < tee_mm_get_size(ctx->mm)) { + *buffer++ = ((section++ + py_offset) << SECTION_SHIFT) | + (TEE_MMU_SECTION_UCODE | TEE_MMU_SECTION_OIWBWA); + section_cnt++; + } + + ctx->mmu->ta_private_vmem_start = TEE_DDR_VLOFFSET << SECTION_SHIFT; + ctx->mmu->ta_private_vmem_end = (TEE_DDR_VLOFFSET + section_cnt) << + SECTION_SHIFT; + + /* + * Map io parameters + */ + res = + tee_mmu_map_io(ctx, &buffer, + ((uint32_t) buffer - (uint32_t) ctx->mmu->table) / 4, + param); + +exit: + if (res != TEE_SUCCESS) { + free(ctx->mmu->table); + ctx->mmu->table = NULL; + ctx->mmu->size = 0; + } + + return res; +} + +/* + * tee_mmu_final - finalise and free ctx mmu + */ +void tee_mmu_final(struct tee_ta_ctx *ctx) +{ + uint32_t asid = 1 << ((ctx->context - 1) & 0xff); + + /* return ASID */ + g_asid |= asid; + g_current_context = 0; + + /* clear MMU entries to avoid clash when asid is reused */ + tee_mmu_invtlb_asid(ctx->context & 0xff); + ctx->context = 0; + + if (ctx->mmu != NULL) { + tee_mmu_info_t *p = ctx->mmu; + free(p->table); + free(ctx->mmu); + } + ctx->mmu = NULL; +} + +/* return true only if buffer fits inside TA private memory */ +bool tee_mmu_is_vbuf_inside_ta_private(const struct tee_ta_ctx *ctx, + const uint32_t va, size_t size) +{ + if ((va + size < va) || + (va < ctx->mmu->ta_private_vmem_start) || + ((va + size) > ctx->mmu->ta_private_vmem_end)) + return false; + return true; +} + +/* return true only if buffer fits outside TA private memory */ +bool tee_mmu_is_vbuf_outside_ta_private(const struct tee_ta_ctx *ctx, + const uint32_t va, size_t size) +{ + if (va + size < va) + return false; + if ((va < ctx->mmu->ta_private_vmem_start) && + ((va + size) > ctx->mmu->ta_private_vmem_start)) + return false; + if ((va < ctx->mmu->ta_private_vmem_end) && + ((va + size) > ctx->mmu->ta_private_vmem_end)) + return false; + return true; +} + +TEE_Result tee_mmu_kernel_to_user(const struct tee_ta_ctx *ctx, + const uint32_t kaddr, uint32_t *uaddr) +{ + uint32_t i = 0; + uint32_t pa; + + if (core_va2pa(kaddr, &pa)) + return TEE_ERROR_SECURITY; + + while (i < ctx->mmu->size) { + if ((pa & (~SECTION_MASK)) == + (ctx->mmu->table[i] & (~SECTION_MASK))) { + *uaddr = (i << SECTION_SHIFT) + (kaddr & SECTION_MASK); + return TEE_SUCCESS; + } + i++; + } + + return TEE_ERROR_ITEM_NOT_FOUND; +} + +TEE_Result tee_mmu_user_va2pa_helper(const struct tee_ta_ctx *ctx, void *ua, + void **pa) +{ + uint32_t n = (uint32_t) ua >> SECTION_SHIFT; + + if (n >= ctx->mmu->size) + return TEE_ERROR_ACCESS_DENIED; + + *pa = (void *)((ctx->mmu->table[n] & ~SECTION_MASK) | + ((uint32_t) ua & SECTION_MASK)); + return TEE_SUCCESS; +} + +/* */ +TEE_Result tee_mmu_user_pa2va_helper(struct tee_ta_ctx *ctx, void *pa, + void **va) +{ + uint32_t i = 0; + + while (i < ctx->mmu->size) { + if (ctx->mmu->table[i] != 0 && + (uint32_t) pa >= (ctx->mmu->table[i] & ~SECTION_MASK) && + (uint32_t) pa < ((ctx->mmu->table[i] & ~SECTION_MASK) + + (1 << SECTION_SHIFT))) { + *va = (void *)((i << SECTION_SHIFT) + + ((uint32_t) pa & SECTION_MASK)); + return TEE_SUCCESS; + } + i++; + } + return TEE_ERROR_ACCESS_DENIED; +} + +TEE_Result tee_mmu_check_access_rights(struct tee_ta_ctx *ctx, + uint32_t flags, tee_uaddr_t uaddr, + size_t len) +{ + tee_uaddr_t a; + uint32_t param_section; + + /* Address wrap */ + if (uaddr + len < uaddr) + return TEE_ERROR_ACCESS_DENIED; + + param_section = TEE_DDR_VLOFFSET + + tee_mm_get_size(ctx->mm_heap_stack) + tee_mm_get_size(ctx->mm); + + for (a = uaddr; a < (uaddr + len); a += SECTION_SIZE) { + uint32_t n = a >> SECTION_SHIFT; + + if (n >= ctx->mmu->size) + return TEE_ERROR_ACCESS_DENIED; + + if ((flags & TEE_MEMORY_ACCESS_ANY_OWNER) != + TEE_MEMORY_ACCESS_ANY_OWNER && n >= param_section) { + void *pa; + TEE_Result res = + tee_mmu_user_va2pa(ctx, (void *)a, &pa); + + if (res != TEE_SUCCESS) + return res; + /* + * Parameters are shared with normal world if they + * aren't in secure DDR. + * + * If the parameters are in secure DDR it's because one + * TA is invoking another TA and in that case there's + * new memory allocated privately for the paramters to + * this TA. + */ + if (!tee_mm_addr_is_within_range + (&tee_mm_sec_ddr, (uint32_t) pa)) + return TEE_ERROR_ACCESS_DENIED; + } + + /* Check Access Protection from L1 entry */ + switch (TEE_MMU_L1_AP(ctx->mmu->table[n])) { + case TEE_MMU_AP_USER_RO: + if ((flags & TEE_MEMORY_ACCESS_WRITE) != 0) + return TEE_ERROR_ACCESS_DENIED; + break; + case TEE_MMU_AP_USER_RW: + break; + default: + return TEE_ERROR_ACCESS_DENIED; + } + } + + return TEE_SUCCESS; +} + +void tee_mmu_set_ctx(struct tee_ta_ctx *ctx) +{ + if (ctx == NULL) { + tee_mmu_switch(core_mmu_get_ttbr0(), 0); + } else { + uint32_t base, va, i; + + base = TEE_MMU_UL1_BASE; + + if (core_pa2va(core_mmu_get_ttbr0_base(), &va)) { + EMSG("unmapped teecore mmu table! trap CPU!"); + assert(0); + } + /* TODO: why not using the same L1 table and play only on ASID + * to identify tee_mmu_is_kmapping() ? + * Do TEEcore need to protect against TA changing the mapping ? + */ + + /* copy teecore mapping (priviledge mapping only) */ + memcpy((void *)base, (void *)va, 16 * 1024); + + /* check the 1st entries are not mapped: we will map uTA in ! */ + for (i = 0; i < (ctx->mmu->size * 4); i += 4) { + if (*(uint32_t *)(base + i) != 0) { + EMSG("mmu table is not clean: cannot add map"); + assert(0); + } + } + + /* copy uTA mapping at begning of mmu table */ + memcpy((void *)base, ctx->mmu->table, ctx->mmu->size * 4); + + /* Change ASID to new value */ + tee_mmu_switch(TEE_MMU_UL1_PA_BASE | TEE_MMU_DEFAULT_ATTRS, + ctx->context); + } + core_tlb_maintenance(TLBINV_CURRENT_ASID, 0); +} + +uintptr_t tee_mmu_get_load_addr(const struct tee_ta_ctx *const ctx) +{ + TEE_ASSERT((ctx->flags & TA_FLAG_EXEC_DDR) != 0); + + return (TEE_DDR_VLOFFSET + tee_mm_get_size(ctx->mm_heap_stack)) << + SECTION_SHIFT; +} + +/* + * tee_mmu_kmap_init - init TA mapping support + * + * TAs are mapped in virtual space [0 32MB]. + * The TA MMU L1 table is always located at TEE_MMU_UL1_BASE. + * The MMU table for a target TA instance will be copied to this address + * when tee core sets up TA context. + */ +void tee_mmu_kmap_init(void) +{ + tee_vaddr_t s = TEE_MMU_UL1_NUM_USER_ENTRIES << SECTION_SHIFT; + tee_vaddr_t e = s + (TEE_MMU_UL1_NUM_KERN_ENTRIES << SECTION_SHIFT); + + if ((TEE_MMU_UL1_PA_BASE % TEE_MMU_UL1_SIZE) != 0) { + DMSG("Bad MMU addr va 0x%x pa 0x%x 0x%x\n", + TEE_MMU_UL1_BASE, TEE_MMU_UL1_PA_BASE, + TEE_MMU_UL1_PA_BASE % TEE_MMU_UL1_SIZE); + assert(0); + } + + /* Configure MMU UL1 */ + memset((void *)TEE_MMU_UL1_BASE, 0, TEE_MMU_UL1_SIZE); + + if (!tee_mm_init(&tee_mmu_virt_kmap, s, e, SECTION_SHIFT, + TEE_MM_POOL_NO_FLAGS)) { + DMSG("Failed to init kmap. Trap CPU!"); + assert(0); + } +} + +TEE_Result tee_mmu_kmap_helper(tee_paddr_t pa, size_t len, void **va) +{ + tee_mm_entry_t *mm; + size_t n; + uint32_t *l1 = (uint32_t *)TEE_MMU_UL1_KERN_BASE; + uint32_t py_offset = (uint32_t) pa >> SECTION_SHIFT; + uint32_t pa_s = TEE_ROUNDDOWN(pa, SECTION_SIZE); + uint32_t pa_e = TEE_ROUNDUP(pa + len, SECTION_SIZE); + uint32_t flags; + + mm = tee_mm_alloc(&tee_mmu_virt_kmap, pa_e - pa_s); + if (mm == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + /* + * check memory attributes (must either secure or unsecured) + * + * Warning: platform depedancy: was is cached and uncached. + */ + flags = TEE_MMU_SECTION_KDATA; + if (tee_pbuf_is_sec(pa, len) == true) { + flags |= TEE_MMU_SECTION_OIWBWA; + } else if (tee_pbuf_is_non_sec(pa, len) == true) { + flags |= TEE_MMU_SECTION_NS; + if (core_mmu_is_shm_cached()) + flags |= TEE_MMU_SECTION_OIWBWA; + else + flags |= TEE_MMU_SECTION_NOCACHE; + } else { + return TEE_ERROR_GENERIC; + } + + for (n = 0; n < tee_mm_get_size(mm); n++) + l1[n + tee_mm_get_offset(mm)] = + ((n + py_offset) << SECTION_SHIFT) | flags; + + core_tlb_maintenance(TLBINV_UNIFIEDTLB, 0); + + *va = (void *)(tee_mm_get_smem(mm) + (pa & SECTION_MASK)); + return TEE_SUCCESS; +} + +void tee_mmu_kunmap(void *va, size_t len) +{ + size_t n; + tee_mm_entry_t *mm; + uint32_t *l1 = (uint32_t *)TEE_MMU_UL1_KERN_BASE; + + mm = tee_mm_find(&tee_mmu_virt_kmap, (uint32_t) va); + if (mm == NULL || len > tee_mm_get_bytes(mm)) + return; /* Invalid range, not much to do */ + + /* Clear the mmu entries */ + for (n = 0; n < tee_mm_get_size(mm); n++) + l1[n + tee_mm_get_offset(mm)] = 0; + + core_tlb_maintenance(TLBINV_UNIFIEDTLB, 0); + tee_mm_free(mm); +} + +TEE_Result tee_mmu_kmap_pa2va_helper(void *pa, void **va) +{ + size_t n; + + for (n = TEE_MMU_UL1_NUM_USER_ENTRIES; + n < TEE_MMU_UL1_NUM_ENTRIES; + n++) { + if (TEE_MMU_UL1_ENTRY(n) != 0 && + (uint32_t) pa >= (TEE_MMU_UL1_ENTRY(n) & ~SECTION_MASK) && + (uint32_t) pa < ((TEE_MMU_UL1_ENTRY(n) & ~SECTION_MASK) + + (1 << SECTION_SHIFT))) { + *va = (void *)((n << SECTION_SHIFT) + + ((uint32_t) pa & SECTION_MASK)); + return TEE_SUCCESS; + } + } + return TEE_ERROR_ACCESS_DENIED; +} + +TEE_Result tee_mmu_kmap_va2pa_helper(void *va, void **pa) +{ + uint32_t n = (uint32_t) va >> SECTION_SHIFT; + + if (n < TEE_MMU_UL1_NUM_USER_ENTRIES && n >= TEE_MMU_UL1_NUM_ENTRIES) + return TEE_ERROR_ACCESS_DENIED; + *pa = (void *)((TEE_MMU_UL1_ENTRY(n) & ~SECTION_MASK) | + ((uint32_t) va & SECTION_MASK)); + return TEE_SUCCESS; +} + +bool tee_mmu_kmap_is_mapped(void *va, size_t len) +{ + tee_vaddr_t a = (tee_vaddr_t) va; + tee_mm_entry_t *mm = tee_mm_find(&tee_mmu_virt_kmap, a); + + if (mm == NULL) + return false; + + if ((a + len) > (tee_mm_get_smem(mm) + tee_mm_get_bytes(mm))) + return false; + + return true; +} + +bool tee_mmu_is_kernel_mapping(void) +{ + return (tee_mmu_get_ttbr0() == core_mmu_get_ttbr0()); +} + +void teecore_init_ta_ram(void) +{ + unsigned int s, e; + + /* get virtual addr/size of RAM where TA are loaded/executedNSec + * shared mem allcated from teecore */ + core_mmu_get_mem_by_type(MEM_AREA_TA_RAM, &s, &e); + + TEE_ASSERT((s & (SECTION_SIZE - 1)) == 0); + TEE_ASSERT((e & (SECTION_SIZE - 1)) == 0); + /* extra check: we could rely on core_mmu_get_mem_by_type() */ + TEE_ASSERT(tee_vbuf_is_sec(s, e - s) == true); + + TEE_ASSERT(tee_mm_is_empty(&tee_mm_sec_ddr)); + + /* remove previous config and init TA ddr memory pool */ + tee_mm_final(&tee_mm_sec_ddr); + tee_mm_init(&tee_mm_sec_ddr, s, e, SECTION_SHIFT, TEE_MM_POOL_NO_FLAGS); +} + +void teecore_init_pub_ram(void) +{ + unsigned int s, e; + unsigned int nsec_tee_size = 32 * 1024; + + /* get virtual addr/size of NSec shared mem allcated from teecore */ + core_mmu_get_mem_by_type(MEM_AREA_NSEC_SHM, &s, &e); + + TEE_ASSERT(s < e); + TEE_ASSERT((s & (SECTION_SIZE - 1)) == 0); + TEE_ASSERT((e & (SECTION_SIZE - 1)) == 0); + /* extra check: we could rely on core_mmu_get_mem_by_type() */ + TEE_ASSERT(tee_vbuf_is_non_sec(s, e - s) == true); + + /* + * 32kByte first bytes are allocated from teecore. + * Remaining is under control of the NSec allocator. + */ + TEE_ASSERT((e - s) > nsec_tee_size); + + TEE_ASSERT(tee_mm_is_empty(&tee_mm_pub_ddr)); + tee_mm_final(&tee_mm_pub_ddr); + tee_mm_init(&tee_mm_pub_ddr, s, s + nsec_tee_size, SMALL_PAGE_SHIFT, + TEE_MM_POOL_NO_FLAGS); + + s += nsec_tee_size; + default_nsec_shm_paddr = s; + default_nsec_shm_size = e - s; +} + +void *tee_mmu_ioremap(tee_paddr_t pa, size_t len) +{ + /* return (void *)ioremap((void *)pa, len); */ + return (void *)NULL; +} + +void tee_mmu_iounmap(void *va) +{ + /* linux API */ + /* iounmap(va); */ +} + +static uint32_t section_to_teesmc_cache_attr(uint32_t sect) +{ + + if (sect & TEE_MMU_SECTION_TEX(4)) { + uint32_t attr = 0; + + if (sect & TEE_MMU_SECTION_TEX(2)) + attr |= TEESMC_ATTR_CACHE_O_WRITE_THR; + if (sect & TEE_MMU_SECTION_TEX(1)) + attr |= TEESMC_ATTR_CACHE_I_WRITE_BACK; + if (sect & TEE_MMU_SECTION_C) + attr |= TEESMC_ATTR_CACHE_O_WRITE_THR; + if (sect & TEE_MMU_SECTION_B) + attr |= TEESMC_ATTR_CACHE_O_WRITE_BACK; + assert(attr == TEESMC_ATTR_CACHE_DEFAULT); + return attr; + } + + switch (sect & TEE_MMU_SECTION_CACHEMASK) { + /* outer and inner write-back */ + /* no write-allocate */ + case TEE_MMU_SECTION_TEX(0) | TEE_MMU_SECTION_B: + /* write-allocate */ + case TEE_MMU_SECTION_TEX(1) | TEE_MMU_SECTION_B | TEE_MMU_SECTION_C: + return TEESMC_ATTR_CACHE_I_WRITE_BACK | + TEESMC_ATTR_CACHE_O_WRITE_BACK; + + /* outer and inner write-through */ + case TEE_MMU_SECTION_TEX(0) | TEE_MMU_SECTION_C: + panic(); + return TEESMC_ATTR_CACHE_I_WRITE_THR | + TEESMC_ATTR_CACHE_O_WRITE_THR; + + /* outer and inner no-cache */ + case TEE_MMU_SECTION_TEX(1): + panic(); + return TEESMC_ATTR_CACHE_I_NONCACHE | + TEESMC_ATTR_CACHE_O_NONCACHE; + default: + panic(); + } +} + +uint32_t tee_mmu_kmap_get_cache_attr(void *va) +{ + uint32_t n = (vaddr_t)va >> SECTION_SHIFT; + + assert(n >= TEE_MMU_UL1_NUM_USER_ENTRIES && + n < TEE_MMU_UL1_NUM_ENTRIES); + + return section_to_teesmc_cache_attr(TEE_MMU_UL1_ENTRY(n)); +} + +uint32_t tee_mmu_user_get_cache_attr(struct tee_ta_ctx *ctx, void *va) +{ + uint32_t n = (vaddr_t)va >> SECTION_SHIFT; + + assert(n < ctx->mmu->size); + + return section_to_teesmc_cache_attr(ctx->mmu->table[n]); +} diff --git a/core/arch/arm32/mm/tee_mmu_unpg.c b/core/arch/arm32/mm/tee_mmu_unpg.c new file mode 100644 index 00000000000..73da99f3963 --- /dev/null +++ b/core/arch/arm32/mm/tee_mmu_unpg.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +void tee_mmu_get_map(struct tee_mmu_mapping *map) +{ + if (map == NULL) + return; + + map->ttbr0 = tee_mmu_get_ttbr0(); + map->ctxid = tee_mmu_get_context(); +} + +void tee_mmu_set_map(struct tee_mmu_mapping *map) +{ + if (map == NULL) + tee_mmu_switch(core_mmu_get_ttbr0(), 0); + else + tee_mmu_switch(map->ttbr0, map->ctxid); + + invalidate_mmu_tlb(); +} diff --git a/core/arch/arm32/mm/tee_mmu_unpg_asm.S b/core/arch/arm32/mm/tee_mmu_unpg_asm.S new file mode 100644 index 00000000000..1867b02c217 --- /dev/null +++ b/core/arch/arm32/mm/tee_mmu_unpg_asm.S @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + + .global tee_mmu_switch + .global tee_mmu_set_context + .global tee_mmu_invtlb_asid + .global tee_mmu_get_ttbr0 + .global tee_mmu_get_context + + .section .text + .balign 4 + .code 32 + + /* + * INPUT - r0, ttbr0 base + * r1, Context ID + * + * Disable IRQ/FIQs during the operation (atomic ASID/TTBR0 loading). + */ + .func tee_mmu_switch +tee_mmu_switch: + + /* save/mask IRQs/FIQs */ + mrs r2, cpsr + and r3, r2, #CPSR_FIQ_IRQ_MASK + orr r2, r2, #CPSR_FIQ_IRQ_MASK + msr cpsr_cxsf, r2 + /* set reserved context id */ + dsb /* ARM erratum 754322 */ + mov r2, #0 + mcr p15, 0, r2, c13, c0, 1 + isb + /* set ttbr0 */ + mcr p15, 0, r0, c2, c0, 0 + isb + /* set context id */ + mcr p15, 0, r1, c13, c0, 1 + isb + /* restore irq/fiq mask */ + mrs r1, cpsr + bic r1, r1, #CPSR_FIQ_IRQ_MASK + orr r1, r1, r3 + msr cpsr_cxsf, r1 + + bx lr + .endfunc + + /* + * INPUT - r0, Context ID + */ + .func tee_mmu_set_context +tee_mmu_set_context: + dsb + mcr p15, 0, r0, c13, c0, 1 + isb + bx lr + .endfunc + + /* + * INPUT - r0, ASID to be invalidated + */ + .func tee_mmu_invtlb_asid +tee_mmu_invtlb_asid: + mcr p15, 0, r0, c8, c3, 2 + dsb + /* No isb due to that we know we will take an exception + * before we need a clean TLB */ + bx lr + .endfunc + + /* + * OUTPUT - r0, ttbr0 base + */ + .func tee_mmu_get_ttbr0 +tee_mmu_get_ttbr0: + mrc p15, 0, r0, c2, c0, 0 + bx lr + .endfunc + + /* + * INPUT - r0, Context ID + */ + .func tee_mmu_get_context +tee_mmu_get_context: + mrc p15, 0, r0, c13, c0, 1 + bx lr + .endfunc diff --git a/core/arch/arm32/mm/tee_pager.c b/core/arch/arm32/mm/tee_pager.c new file mode 100644 index 00000000000..ed68b9aef10 --- /dev/null +++ b/core/arch/arm32/mm/tee_pager.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +void tee_pager_add_pages(tee_vaddr_t vaddr, size_t npages) +{ + size_t n; + + /* setup memory */ + for (n = 0; n < npages; n++) { + struct tee_pager_pmem *apage; + tee_vaddr_t va = vaddr + n * SMALL_PAGE_SIZE; + uint32_t *mmu_entry = tee_pager_get_mmu_entry(va); + + /* Ignore unmapped entries */ + if (*mmu_entry == 0) + continue; + + apage = malloc(sizeof(struct tee_pager_pmem)); + if (apage == NULL) { + DMSG("Can't allocate memory"); + while (1) + ; + } + + apage->mmu_entry = (uint32_t *)mmu_entry; + + /* + * Set to TEE_PAGER_NO_ACCESS_ATTRIBUTES and not + * TEE_PAGER_PAGE_UNLOADED since pager would misstake it for a + * hidden page in case the virtual address was reused before + * the physical page was used for another virtual page. + */ + *mmu_entry = (*mmu_entry & ~SMALL_PAGE_MASK) | + TEE_PAGER_NO_ACCESS_ATTRIBUTES; + apage->ctx_handle = NULL; + + TAILQ_INSERT_TAIL(&tee_pager_pmem_head, apage, link); + tee_pager_npages++; + } + + /* Invalidate secure TLB */ + core_tlb_maintenance(TLBINV_UNIFIEDTLB, 0); +} + +void tee_pager_unmap(uint32_t page, uint8_t psize) +{ + int i; + + if ((page & 0xFFF) != 0) { + EMSG("Invalid page address"); + while (1) + ; + } + + for (i = 0; i < psize; i++) { + uint32_t addr = page + (i << SMALL_PAGE_SHIFT); + uint32_t *mmu_entry = tee_pager_get_mmu_entry(addr); + + if (*mmu_entry != 0) { + struct tee_pager_pmem *apage; + + /* Invalidate mmu_entry */ + *mmu_entry &= ~SMALL_PAGE_MASK; + + /* + * Unregister the session from the page entry using + * this mmu_entry. + */ + TAILQ_FOREACH(apage, &tee_pager_pmem_head, link) { + if (apage->mmu_entry == (uint32_t *)mmu_entry) { + apage->ctx_handle = NULL; + break; + } + } + + if (apage == NULL) { + EMSG("Physical page to unmap not found"); + while (1) + ; + } + } + } + + /* Invalidate secure TLB */ + core_tlb_maintenance(TLBINV_UNIFIEDTLB, 0); +} + +void tee_pager_unhide_all_pages(void) +{ + struct tee_pager_pmem *apage; + bool has_hidden_page = false; + + TAILQ_FOREACH(apage, &tee_pager_pmem_head, link) { + if ((*apage->mmu_entry & 0xfff) == TEE_PAGER_PAGE_UNLOADED) { + /* Page is hidden, unhide it */ + has_hidden_page = true; + *apage->mmu_entry |= 0x10; + } + } + + /* Only invalidate secure TLB if something was changed */ + if (has_hidden_page) + core_tlb_maintenance(TLBINV_UNIFIEDTLB, 0); +} diff --git a/core/arch/arm32/mm/tee_pager_unpg.c b/core/arch/arm32/mm/tee_pager_unpg.c new file mode 100644 index 00000000000..9c81efa4291 --- /dev/null +++ b/core/arch/arm32/mm/tee_pager_unpg.c @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +/* Dummies to allow the macros to be left at current places below */ +#define TEE_PAGER_RECORD_FAULT(x) do { } while (0) +#define TEE_PAGER_SET_OLD_VA(x) do { } while (0) +#define TEE_PAGER_SET_PA(x) do { } while (0) +#define TEE_PAGER_SET_COPY(x) do { } while (0) +#define TEE_PAGER_SET_UNHIDE(x) do { } while (0) +#define TEE_PAGER_DUMP_RECORDING() do { } while (0) +#define TEE_PRINT_SAVED_REGS() do { } while (0) + +/* The list of physical pages. The first page in the list is the oldest */ +struct tee_pager_pmem_head tee_pager_pmem_head = +TAILQ_HEAD_INITIALIZER(tee_pager_pmem_head); + +/* number of pages hidden */ +#define TEE_PAGER_NHIDE (tee_pager_npages / 3) + +/* number of pages */ +uint8_t tee_pager_npages; + +static bool tee_pager_is_monitor_exception(void) +{ + return (tee_pager_get_spsr() & TEE_PAGER_SPSR_MODE_MASK) == + TEE_PAGER_SPSR_MODE_MON; +} + +bool tee_pager_is_user_exception(void) +{ + return (tee_pager_get_spsr() & TEE_PAGER_SPSR_MODE_MASK) == + TEE_PAGER_SPSR_MODE_USR; +} + +bool tee_pager_is_abort_in_abort_handler(void) +{ + return (tee_pager_get_spsr() & TEE_PAGER_SPSR_MODE_MASK) == + TEE_PAGER_SPSR_MODE_ABT; +} + +static void tee_pager_print_abort(const uint32_t addr, const uint32_t fsr, + const uint32_t pc, const uint32_t flags, + const uint32_t dbgpcsr) +{ + DMSG("%s at 0x%x: FSR 0x%x PC 0x%x TTBR0 0x%X CONTEXIDR 0x%X", + (flags == TEE_PAGER_DATA_ABORT) ? "data-abort" : + (flags == TEE_PAGER_PREF_ABORT) ? "prefetch-abort" : "undef-abort", + addr, fsr, pc, tee_mmu_get_ttbr0(), tee_mmu_get_context()); + DMSG("CPUID %dd DBGPCSR 0x%x SPSR_abt 0x%x", + TEE_PAGER_GET_CPUID_asm(), dbgpcsr, tee_pager_get_spsr()); +} + +static void tee_pager_print_error_abort(const uint32_t addr, const uint32_t fsr, + const uint32_t pc, const uint32_t flags, + const uint32_t dbgpcsr) +{ + EMSG("%s at 0x%x\n" + "FSR 0x%x PC 0x%x TTBR0 0x%X CONTEXIDR 0x%X\n" + "CPUID 0x%x DBGPCSR 0x%x CPSR 0x%x (read from SPSR)", + (flags == TEE_PAGER_DATA_ABORT) ? "data-abort" : + (flags == TEE_PAGER_PREF_ABORT) ? "prefetch-abort" : "undef-abort", + addr, fsr, pc, tee_mmu_get_ttbr0(), tee_mmu_get_context(), + TEE_PAGER_GET_CPUID_asm(), dbgpcsr, tee_pager_get_spsr()); +} + +static uint32_t tee_pager_handle_abort(const uint32_t flags, const uint32_t pc, + const uint32_t dbgpcsr) +{ + struct tee_pager_pmem *apage; + uint32_t addr; + uint32_t w_addr; + uint32_t i; + uint32_t fsr; + + if (flags == TEE_PAGER_DATA_ABORT) { + fsr = TEE_PAGER_GET_DFSR_asm(); + addr = TEE_PAGER_GET_DFAR_asm(); + } else { + if (flags == TEE_PAGER_PREF_ABORT) { + fsr = TEE_PAGER_GET_IFSR_asm(); + addr = TEE_PAGER_GET_IFAR_asm(); + } else { + fsr = 0; + addr = pc; + } + } + + w_addr = addr; + + /* + * w_addr is the address that we intend to handle to the page fault + * for. This is normally the same as addr except in the case where we + * have thumb instruction spread over two pages and the first page + * already is available. In that case will addr still be the beginning + * of the instruction even if the fault really is for the second page. + */ + + /* In case of multithreaded version, this section must be protected */ + + if (tee_pager_is_user_exception()) { + tee_pager_print_error_abort(addr, fsr, pc, flags, dbgpcsr); + EMSG("[TEE_PAGER] abort in User mode (TA will panic)"); + return TEE_PAGER_USER_TA_PANIC; + } + + if (tee_pager_is_monitor_exception()) + EMSG("[TEE_PAGER] abort in monitor!"); + + if (tee_pager_is_abort_in_abort_handler()) { + tee_pager_print_error_abort(addr, fsr, pc, flags, dbgpcsr); + EMSG("[TEE_PAGER] abort in abort handler (trap CPU)"); + while (1) + ; + } + + if (flags == TEE_PAGER_UNDEF_ABORT) { + tee_pager_print_error_abort(addr, fsr, pc, flags, dbgpcsr); + EMSG("[TEE_PAGER] undefined abort (trap CPU)"); + while (1) + ; + } + + switch (fsr & TEE_FSR_FS_MASK) { + case TEE_FSR_FS_ALIGNMENT_FAULT: /* Only possible for data abort */ + tee_pager_print_error_abort(addr, fsr, pc, flags, dbgpcsr); + EMSG("[TEE_PAGER] alignement fault! (trap CPU)"); + while (1) + ; + + case TEE_FSR_FS_DEBUG_EVENT: + tee_pager_print_abort(addr, fsr, pc, flags, dbgpcsr); + DMSG("[TEE_PAGER] Ignoring debug event!"); + return TEE_PAGER_NORMAL_RETURN; + + case TEE_FSR_FS_ASYNC_EXTERNAL_ABORT: /* Only possible for data abort */ + tee_pager_print_abort(addr, fsr, pc, flags, dbgpcsr); + DMSG("[TEE_PAGER] Ignoring async external abort!"); + return TEE_PAGER_NORMAL_RETURN; + + default: +#ifdef PAGER_DEBUG_PRINT + tee_pager_print_abort(addr, fsr, pc, flags, dbgpcsr); +#endif + break; + } + +#ifndef CFG_TEE_PAGER + /* + * Until PAGER is supported, trap CPU here. + */ + tee_pager_print_error_abort(addr, fsr, pc, flags, dbgpcsr); + EMSG("Unexpected page fault! Trap CPU"); + while (1) + ; +#endif + + TEE_PAGER_RECORD_FAULT(addr); + + /* check if the access is valid */ + if (!tee_mm_validate(&tee_mm_vcore, w_addr)) { + tee_pager_print_abort(addr, fsr, pc, flags, dbgpcsr); + DMSG("Invalid addr 0x%" PRIx32, addr); + TEE_PRINT_SAVED_REGS(); + TEE_PAGER_DUMP_RECORDING(); + while (1) + ; + } + + /* check if page is hidden */ + TAILQ_FOREACH(apage, &tee_pager_pmem_head, link) { + if (((*apage->mmu_entry & 0xFFF) == TEE_PAGER_PAGE_UNLOADED) && + apage->ctx_handle != NULL && + w_addr >= TEE_PAGER_GET_VA(apage->mmu_entry) && + w_addr < + TEE_PAGER_GET_VA(apage->mmu_entry) + SMALL_PAGE_SIZE) { + /* page is hidden, show and move to back */ + *(apage->mmu_entry) |= TEE_MMU_L2SP_PRIV_ACC; + TEE_PAGER_SET_UNHIDE(1); + TEE_PAGER_SET_PA((*(apage->mmu_entry)) & 0xFFFFF000); + + TAILQ_REMOVE(&tee_pager_pmem_head, apage, link); + TAILQ_INSERT_TAIL(&tee_pager_pmem_head, apage, link); + + w_addr = 0; + + break; + } + } + + if (apage == NULL) { + /* the page wasn't hidden */ + uint32_t pa; + uint32_t *mmu_entry = + (uint32_t *)tee_pager_get_mmu_entry((tee_vaddr_t) w_addr); + + if (*mmu_entry != 0) { + /* + * There's an pmem entry using this mmu entry, let's use + * that entry in the new mapping. + */ + TAILQ_FOREACH(apage, &tee_pager_pmem_head, link) { + if (apage->mmu_entry == mmu_entry) + break; + } + if (apage == NULL) { + tee_pager_print_abort(addr, fsr, pc, flags, + dbgpcsr); + DMSG("Couldn't find pmem for mmu_entry %p", + (void *)mmu_entry); + while (1) + ; + } + } else { + apage = TAILQ_FIRST(&tee_pager_pmem_head); + if (apage == NULL) { + tee_pager_print_abort(addr, fsr, pc, flags, + dbgpcsr); + DMSG("No pmem entries"); + while (1) + ; + } + } + + TEE_PAGER_SET_OLD_VA(TEE_PAGER_GET_VA(apage->mmu_entry)); + + /* save rw data if needed */ + if ((*apage->mmu_entry & 0xFFF) != 0 && + tee_ta_check_rw(TEE_PAGER_GET_VA(apage->mmu_entry), + apage->ctx_handle)) { + /* make sure the page is accessible */ + if (((*apage->mmu_entry & 0xFFF) == + TEE_PAGER_PAGE_UNLOADED)) { + *apage->mmu_entry |= TEE_MMU_L2SP_PRIV_ACC; + + /* Invalidate secure TLB */ + core_tlb_maintenance(TLBINV_UNIFIEDTLB, 0); + } + + tee_ta_save_rw(TEE_PAGER_GET_VA(apage->mmu_entry), + apage->ctx_handle); + } + + /* move page to back */ + TAILQ_REMOVE(&tee_pager_pmem_head, apage, link); + TAILQ_INSERT_TAIL(&tee_pager_pmem_head, apage, link); + + /* add page to mmu table, small pages [31:12]PA */ + pa = *apage->mmu_entry & 0xFFFFF000; + TEE_PAGER_SET_PA(pa); + + *apage->mmu_entry = 0; + apage->mmu_entry = mmu_entry; + + *apage->mmu_entry = pa | TEE_PAGER_PAGE_LOADED; + +#ifdef PAGER_DEBUG_PRINT + DMSG("Mapped %p -> %p", w_addr & 0xFFFFF000, pa); +#endif + } + + /* Hide */ + { + struct tee_pager_pmem *bpage; + + i = 0; + TAILQ_FOREACH(bpage, &tee_pager_pmem_head, link) { + if (i >= TEE_PAGER_NHIDE) + break; + i++; + *bpage->mmu_entry = + TEE_MMU_L2SP_CLEAR_ACC(*bpage->mmu_entry); + } + } + + /* Invalidate secure TLB */ + core_tlb_maintenance(TLBINV_UNIFIEDTLB, 0); + + if (w_addr) { + /* load page code & data */ + apage->ctx_handle = tee_ta_load_page(w_addr); + TEE_PAGER_SET_COPY(1); + + core_cache_maintenance(DCACHE_AREA_CLEAN, + (void *)(w_addr & 0xFFFFF000), + SMALL_PAGE_SIZE); + + core_cache_maintenance(ICACHE_AREA_INVALIDATE, + (void *)(w_addr & 0xFFFFF000), + SMALL_PAGE_SIZE); + } + + /* end protect (multithreded version) */ + + /* + * Until now we've been running with IRQ blocked. Let's enble IRQ now + * when it should be safe to do further processing with them enabled. + * + * It should be possible to enable IRQ earlier, but MMU updates and + * cache mainentance may need some tweaking to guarentee coherency in + * case we switch CPU in the middle of an operation. + */ + tee_pager_restore_irq(); + + return TEE_PAGER_NORMAL_RETURN; +} + +void tee_pager_abort_handler(uint32_t abort_type, + struct thread_abort_regs *regs) +{ + static const uint32_t abort_type_to_flags[] = { + TEE_PAGER_UNDEF_ABORT, + TEE_PAGER_PREF_ABORT, + TEE_PAGER_DATA_ABORT, + }; + uint32_t res; + + res = tee_pager_handle_abort(abort_type_to_flags[abort_type], + regs->lr, 0); + if (res == TEE_PAGER_USER_TA_PANIC) { + /* + * It was a user exception, stop user execution and return + * to TEE Core. + */ + regs->r0 = 0xdeadbeef; + regs->lr = (uint32_t)tee_svc_user_ta_panic_from_pager; + regs->spsr = read_cpsr(); + regs->spsr &= ~TEE_PAGER_SPSR_MODE_MASK; + regs->spsr |= TEE_PAGER_SPSR_MODE_SVC; + /* Select Thumb or ARM mode */ + if (regs->lr & 1) + regs->spsr |= CPSR_T; + else + regs->spsr &= ~CPSR_T; + } +} + +void tee_pager_restore_irq(void) +{ + /* + * Restores the settings of IRQ as saved when entering secure + * world, using something like + * INTERRUPT_ENABLE(SEC_ENV_SETTINGS_READ() & SEC_ROM_IRQ_ENABLE_MASK); + */ + + /* Make a crash on purpose as this is not implemented yet */ + int *p = 0; + *p = 1; +} diff --git a/core/arch/arm32/mm/tee_pager_unpg_asm.S b/core/arch/arm32/mm/tee_pager_unpg_asm.S new file mode 100644 index 00000000000..ed0a09547d3 --- /dev/null +++ b/core/arch/arm32/mm/tee_pager_unpg_asm.S @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +.global TEE_PAGER_INIT_asm +.global TEE_PAGER_VECT_TABLE +.global TEE_PAGER_GET_IFAR_asm +.global TEE_PAGER_GET_DFAR_asm +.global TEE_PAGER_GET_DFSR_asm +.global TEE_PAGER_GET_IFSR_asm +.global TEE_PAGER_GET_CPUID_asm +.global tee_pager_get_spsr +.global TEE_PAGER_RES_asm + + +.set TEE_PAGER_reset_addr, 0xffff0000 +.set TEE_PAGER_res_addr, 0xffff0014 +.set TEE_PAGER_fiq_addr, 0xffff001c + +.section .text +.balign 4 +.code 32 + +.func TEE_PAGER_GET_CPUID_asm +TEE_PAGER_GET_CPUID_asm: + mrc p15,0,r0,c0,c0,5 @ Read Multiprocessor Affinity Register + bx lr +.endfunc + +.func TEE_PAGER_GET_IFAR_asm +TEE_PAGER_GET_IFAR_asm: + mrc p15, 0, r0, c6, c0, 2 + bx lr +.endfunc + +.func TEE_PAGER_GET_DFAR_asm +TEE_PAGER_GET_DFAR_asm: + mrc p15, 0, r0, c6, c0, 0 + bx lr +.endfunc + +.func TEE_PAGER_GET_DFSR_asm +TEE_PAGER_GET_DFSR_asm: + mrc p15, 0, r0, c5, c0, 0 + bx lr +.endfunc + +.func TEE_PAGER_GET_IFSR_asm +TEE_PAGER_GET_IFSR_asm: + mrc p15, 0, r0, c5, c0, 1 + bx lr +.endfunc + +/* uint32_t tee_pager_get_spsr(void); */ +.func tee_pager_get_spsr +tee_pager_get_spsr: + mrs r0, spsr + bx lr +.endfunc + +.func TEE_PAGER_INIT_asm +TEE_PAGER_INIT_asm: + push {r4, lr} + + @ Update configuration of TTBR0 + mrc p15, 0, r4, c2, c0, 0 + mcr p15, 0, r4, c2, c0, 0 + + @ Change to TTBR1 + mcr p15, 0, r4, c2, c0, 1 + mrc p15, 0, r4, c2, c0, 2 + orr r4, r4, #7 + mcr p15, 0, r4, c2, c0, 2 + + pop {r4, pc} + +.endfunc + diff --git a/core/arch/arm32/plat-orly2/.gitignore b/core/arch/arm32/plat-orly2/.gitignore new file mode 100644 index 00000000000..49b7bb9eb2b --- /dev/null +++ b/core/arch/arm32/plat-orly2/.gitignore @@ -0,0 +1 @@ +System.map diff --git a/core/arch/arm32/plat-orly2/asc.S b/core/arch/arm32/plat-orly2/asc.S new file mode 100644 index 00000000000..4cd3e364092 --- /dev/null +++ b/core/arch/arm32/plat-orly2/asc.S @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef STXH416_LPM_PERIPH_BASE +#define STXH416_LPM_PERIPH_BASE 0xFE400000 +#endif + +#define ASC_NUM 21 + +#ifndef ST_ASC21_REGS_BASE +#define ST_ASC21_REGS_BASE (STXH416_LPM_PERIPH_BASE + 0x00131000) +#endif + +#define ST_32BIT_REG(address) (address) + +/* Asynchronous Serial Controller control registers */ +#ifndef ST_ASC_REGS_BASE +#define ST_ASC_REGS_BASE(n) ST_ASC##n##_REGS_BASE +#endif /* !ST_ASC_REGS_BASE */ +#define ST_ASC_BAUDRATE(n) ST_32BIT_REG(ST_ASC_REGS_BASE(n) + 0x00) +#define ST_ASC_TXBUFFER(n) ST_32BIT_REG(ST_ASC_REGS_BASE(n) + 0x04) +#define ST_ASC_RXBUFFER(n) ST_32BIT_REG(ST_ASC_REGS_BASE(n) + 0x08) +#define ST_ASC_CONTROL(n) ST_32BIT_REG(ST_ASC_REGS_BASE(n) + 0x0c) +#define ST_ASC_INTENABLE(n) ST_32BIT_REG(ST_ASC_REGS_BASE(n) + 0x10) +#define ST_ASC_STATUS(n) ST_32BIT_REG(ST_ASC_REGS_BASE(n) + 0x14) +#define ST_ASC_GUARDTIME(n) ST_32BIT_REG(ST_ASC_REGS_BASE(n) + 0x18) +#define ST_ASC_TIMEOUT(n) ST_32BIT_REG(ST_ASC_REGS_BASE(n) + 0x1c) +#define ST_ASC_TXRESET(n) ST_32BIT_REG(ST_ASC_REGS_BASE(n) + 0x20) +#define ST_ASC_RXRESET(n) ST_32BIT_REG(ST_ASC_REGS_BASE(n) + 0x24) +#define ST_ASC_RETRIES(n) ST_32BIT_REG(ST_ASC_REGS_BASE(n) + 0x28) + +#define BOARD_ASC_BAUDRATE_REG ST_ASC_BAUDRATE(ASC_NUM) +#define BOARD_ASC_CONTROL_REG ST_ASC_CONTROL(ASC_NUM) +#define BOARD_ASC_TXBUFFER_REG ST_ASC_TXBUFFER(ASC_NUM) +#define BOARD_ASC_STATUS_REG ST_ASC_STATUS(ASC_NUM) +#define BOARD_ASC_TXRESET_REG ST_ASC_TXRESET(ASC_NUM) +#define BOARD_ASC_RXRESET_REG ST_ASC_RXRESET(ASC_NUM) + +.section .text +.align 5 + +/* + * int asc_init(void) - init ASC driver. + * + * At least only maps (MMU) the ASC register addresses. + * We rely on some other SW layer to enable ASC IP (power/clamps/clocks/...) + */ +.global asc_init +.type asc_init, %function + +asc_init: + /* TODO: insure ASC is mapped (check against core_init_mmu()/core_mmu.c) */ + ldr r0, =0 + bx lr + +/* + * int __asc_xmit(char*) - Transmit a numm terminated string. + * + * R0 is pointer to null-terminated string + * Clobbers r0-r3 + */ + .global __asc_xmit + .type __asc_xmit, %function + +__asc_xmit: + LDR r2, =BOARD_ASC_TXBUFFER_REG + LDR r3, =BOARD_ASC_STATUS_REG + + /* Output byte */ +nextchr: + /* Spin until TX FIFO ready */ +crwait: + LDR r1, [r3] + ANDS r1, r1, #0x04 /* AND TX FIFO HALF EMPTY flag */ + BEQ crwait /* ANDS should have set Z bit if zero */ + + LDRB r1, [r0], #1 + ANDS r1, r1, r1 + BEQ asc_exit + CMP r1, #0xa /* r1 == \n (line feed) ? */ + BNE notlf + + /* Transmit character extra carriage return for each line feed */ + LDR r1, =0x0d + STR r1, [r2] + + LDR r1, =0x0a /* replace line feed */ + +notlf: + /* Transmit character */ + STR r1, [r2] + + /* Keep going */ + B nextchr +asc_exit: + LDR r0, =0 + BX lr + +/* + * void __asc_flush(void) - flush ASC tx fifo. + * + * Clobbers r0-r3 + */ + .global __asc_flush + .type __asc_flush, %function + +__asc_flush: + LDR r3, =BOARD_ASC_STATUS_REG + +flush_wait: + LDR r1, [r3] + ANDS r1, r1, #0x02 /* AND TX FIFO EMPTY flag */ + BEQ flush_wait /* ANDS should have set Z bit if zero */ + + LDR r0, =0 + BX lr + +/* + * int __asc_xmit_char(char) - Transmit a single character. + * + * R0 is the 1-byte character to be transmited + * Clobbers r0-r3 + */ + .global __asc_xmit_char + .type __asc_xmit_char, %function + +__asc_xmit_char: + LDR r2, =BOARD_ASC_TXBUFFER_REG + LDR r3, =BOARD_ASC_STATUS_REG + + /* Output byte */ + + /* Spin until TX FIFO ready */ +__asc_char_crwait: + LDR r1, [r3] + ANDS r1, r1, #0x04 /* AND TX FIFO HALF EMPTY flag */ + BEQ __asc_char_crwait /* ANDS should have set Z bit if zero */ + + MOVS r1, r0 + LDR r0, =0xFF + AND r1, r1, r0 + BEQ __asc_char_exit + CMP r1, #0xa /* r1 == \n (line feed) ? */ + BNE __asc_char_notlf + + /* Transmit character extra carriage return for each line feed */ + LDR r1, =0x0d + STR r1, [r2] + + LDR r1, =0x0a /* replace line feed */ + +__asc_char_notlf: + /* Transmit character */ + STR r1, [r2] + +__asc_char_exit: + LDR r0, =0 + BX lr \ No newline at end of file diff --git a/core/arch/arm32/plat-orly2/conf.mk b/core/arch/arm32/plat-orly2/conf.mk new file mode 100644 index 00000000000..893faae617a --- /dev/null +++ b/core/arch/arm32/plat-orly2/conf.mk @@ -0,0 +1,69 @@ +CROSS_PREFIX ?= armv7-linux +CROSS_COMPILE ?= $(CROSS_PREFIX)- +include mk/gcc.mk + +platform-cpuarch = cortex-a9 +platform-cflags = -mcpu=$(platform-cpuarch) -mthumb +platform-cflags += -pipe -mthumb-interwork -mlong-calls +platform-cflags += -fno-short-enums -mno-apcs-float -fno-common +platform-aflags = -mcpu=$(platform-cpuarch) +core-platform-cppflags = -I$(arch-dir)/include +core-platform-cppflags += -DNUM_THREADS=2 +core-platform-cppflags += -DWITH_STACK_CANARIES=1 +user_ta-platform-cflags = -fpie + +DEBUG ?= 1 +ifeq ($(DEBUG),1) +platform-cflags += -O0 +else +platform-cflags += -Os +endif +platform-cflags += -g +platform-aflags += -g + +core-platform-subdirs += \ + $(addprefix $(arch-dir)/, kernel mm sm tee sta) $(platform-dir) + +libutil_with_isoc := y + +include mk/config.mk +include $(platform-dir)/system_config.in + +core-platform-cppflags += -DCFG_TEE_CORE_NB_CORE=$(CFG_TEE_CORE_NB_CORE) + +CFG_TEE_CORE_EMBED_INTERNAL_TESTS?=1 +core-platform-cppflags += \ + -DCFG_TEE_CORE_EMBED_INTERNAL_TESTS=$(CFG_TEE_CORE_EMBED_INTERNAL_TESTS) + +core-platform-cppflags += \ + -DCFG_DDR_TEETZ_RESERVED_START=$(CFG_DDR_TEETZ_RESERVED_START) \ + -DCFG_DDR_TEETZ_RESERVED_SIZE=$(CFG_DDR_TEETZ_RESERVED_SIZE) + +core-platform-cppflags += -DTEE_USE_DLMALLOC +core-platform-cppflags += -D_USE_SLAPORT_LIB + + +# define flag to support booting from GDB +core-platform-cppflags += -DCONFIG_TEE_GDB_BOOT +core-platform-cppflags += -DCFG_NO_TA_HASH_SIGN + +core-platform-cppflags += -DSTACK_TMP_SIZE=$(STACK_TMP_SIZE) +core-platform-cppflags += -DSTACK_ABT_SIZE=$(STACK_ABT_SIZE) +core-platform-cppflags += -DSTACK_THREAD_SIZE=$(STACK_THREAD_SIZE) + +ifdef DDR_PHYS_START +core-platform-cppflags += -DCFG_DDR_START=$(DDR_PHYS_START) +core-platform-cppflags += -DCFG_DDR_SIZE=$(DDR_SIZE) +endif +ifdef DDR1_PHYS_START +core-platform-cppflags += -DCFG_DDR1_START=$(DDR1_PHYS_START) +core-platform-cppflags += -DCFG_DDR1_SIZE=$(DDR1_SIZE) +endif + + +PRIMARY_STARTUP_PHYS = \ + 0x$(shell grep stext $(platform-dir)/System.map | grep -v _stext | \ + cut -d' ' -f 1) +SECONDARY_STARTUP_PHYS = \ + 0x$(shell grep stm_secondary_startup $(platform-dir)/System.map | \ + cut -d' ' -f 1) diff --git a/core/arch/arm32/plat-orly2/core_bootcfg.c b/core/arch/arm32/plat-orly2/core_bootcfg.c new file mode 100644 index 00000000000..9e14799e4bc --- /dev/null +++ b/core/arch/arm32/plat-orly2/core_bootcfg.c @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include + +#ifndef CFG_DDR_TEETZ_RESERVED_START +#error "TEETZ reserved DDR start address undef: CFG_DDR_TEETZ_RESERVED_START" +#endif +#ifndef CFG_DDR_TEETZ_RESERVED_SIZE +#error "TEETZ reserved DDR siez undefined: CFG_DDR_TEETZ_RESERVED_SIZE" +#endif + +/* + * TEE/TZ RAM layout: + * + * +-----------------------------------------+ <- CFG_DDR_TEETZ_RESERVED_START + * | TEETZ private RAM | TEE_RAM | ^ + * | +--------------------+ | + * | | TA_RAM | | + * +-----------------------------------------+ | CFG_DDR_TEETZ_RESERVED_SIZE + * | | teecore alloc | | + * | TEE/TZ and NSec | PUB_RAM --------| | + * | shared memory | NSec alloc | | + * +-----------------------------------------+ v + * + * TEE_RAM : 1MByte + * PUB_RAM : 1MByte + * TA_RAM : all what is left (at least 2MByte !) + */ + +/* define the several memory area sizes */ +#if (CFG_DDR_TEETZ_RESERVED_SIZE < (4 * 1024 * 1024)) +#error "Invalid CFG_DDR_TEETZ_RESERVED_SIZE: at least 4MB expected" +#endif + +#define CFG_PUB_RAM_SIZE (1 * 1024 * 1024) +#define CFG_TEE_RAM_SIZE (1 * 1024 * 1024) +#define CFG_TA_RAM_SIZE (CFG_DDR_TEETZ_RESERVED_SIZE - \ + CFG_TEE_RAM_SIZE - CFG_PUB_RAM_SIZE) + +/* define the secure/unsecure memory areas */ +#define CFG_DDR_ARMTZ_ONLY_START (CFG_DDR_TEETZ_RESERVED_START) +#define CFG_DDR_ARMTZ_ONLY_SIZE (CFG_TEE_RAM_SIZE + CFG_TA_RAM_SIZE) + +#define CFG_DDR_ARM_ARMTZ_START \ + (CFG_DDR_ARMTZ_ONLY_START + CFG_DDR_ARMTZ_ONLY_SIZE) +#define CFG_DDR_ARM_ARMTZ_SIZE (CFG_PUB_RAM_SIZE) + +/* define the memory areas (TEE_RAM must start at reserved DDR start addr */ +#define CFG_TEE_RAM_START (CFG_DDR_ARMTZ_ONLY_START) +#define CFG_TA_RAM_START (CFG_TEE_RAM_START + CFG_TEE_RAM_SIZE) +#define CFG_PUB_RAM_START (CFG_TA_RAM_START + CFG_TA_RAM_SIZE) + + +/* + * define the platform memory Secure layout + */ +struct memaccess_area { + unsigned long paddr; + size_t size; +}; +#define MEMACCESS_AREA(a, s) { .paddr = a, .size = s } + +static struct memaccess_area ddr[] = { + MEMACCESS_AREA(CFG_DDR_START, CFG_DDR_SIZE), +#ifdef CFG_DDR1_START + MEMACCESS_AREA(CFG_DDR1_START, CFG_DDR1_SIZE), +#endif +}; + +static struct memaccess_area secure_only = +MEMACCESS_AREA(CFG_DDR_ARMTZ_ONLY_START, CFG_DDR_ARMTZ_ONLY_SIZE); + +static struct memaccess_area nsec_shared = +MEMACCESS_AREA(CFG_DDR_ARM_ARMTZ_START, CFG_DDR_ARM_ARMTZ_SIZE); + +/* + * buf_inside_area - return true is buffer fits in target area + * + * @bp: buffer physical address + * @bs: buffer size in bytes + * @ap: memory physical address + * @as: memory size in bytes + */ +static bool buf_inside_area(unsigned long bp, size_t bs, unsigned long ap, + size_t as) +{ + /* not malformed input data */ + if (((bp + bs - 1) < bp) || + ((ap + as - 1) < ap) || + (bs == 0) || + (as == 0)) + return false; + + if ((bp < ap) || ((bp + bs) > (ap + as))) + return false; + + return true; +} + +/* + * buf_overlaps_area - return true is buffer overlaps target area + * + * @bp: buffer physical address + * @bs: buffer size in bytes + * @ap: memory physical address + * @as: memory size in bytes + */ +static bool buf_overlaps_area(unsigned long bp, size_t bs, unsigned long ap, + size_t as) +{ + /* not malformed input data */ + if (((bp + bs - 1) < bp) || + ((ap + as - 1) < ap) || + (bs == 0) || + (as == 0)) + return false; + + if ((bp < ap) || ((bp + bs) > ap)) + return false; + + if ((bp >= ap) || (bp < (ap + as))) + return false; + + return true; +} + +static bool pbuf_is_ddr(unsigned long paddr, size_t size) +{ + int i = sizeof(ddr) / sizeof(*ddr); + + while (i--) { + if (buf_inside_area(paddr, size, ddr[i].paddr, ddr[i].size)) + return true; + } + return false; +} + +static bool pbuf_is_multipurpose(unsigned long paddr, size_t size) +{ + if (buf_overlaps_area(paddr, size, secure_only.paddr, secure_only.size)) + return false; + if (buf_overlaps_area(paddr, size, nsec_shared.paddr, nsec_shared.size)) + return false; + if (buf_overlaps_area(paddr, size, nsec_shared.paddr, nsec_shared.size)) + return false; + + return pbuf_is_ddr(paddr, size); +} + +/* + * Wrapper for the platform specific pbuf_is() service. + */ +static bool pbuf_is(enum buf_is_attr attr, unsigned long paddr, size_t size) +{ + switch (attr) { + case CORE_MEM_SEC: + if (buf_inside_area + (paddr, size, secure_only.paddr, secure_only.size)) + return true; + return false; + + case CORE_MEM_NON_SEC: + return buf_inside_area(paddr, size, nsec_shared.paddr, + nsec_shared.size); + + case CORE_MEM_MULTPURPOSE: + return pbuf_is_multipurpose(paddr, size); + + case CORE_MEM_EXTRAM: + return pbuf_is_ddr(paddr, size); + + default: + EMSG("unpexted request: attr=%X", attr); + return false; + } +} + +static struct map_area bootcfg_stih416_memory[] = { + { /* teecore execution RAM */ + .type = MEM_AREA_TEE_RAM, + .pa = CFG_TEE_RAM_START, .size = CFG_TEE_RAM_SIZE, + .cached = true, .secure = true, .rw = true, .exec = true, + }, + + { /* teecore TA load/exec RAM - Secure, exec user only! */ + .type = MEM_AREA_TA_RAM, + .pa = CFG_TA_RAM_START, .size = CFG_TA_RAM_SIZE, + .cached = true, .secure = true, .rw = true, .exec = false, + }, + + { /* teecore public RAM - NonSecure, non-exec. */ + .type = MEM_AREA_NSEC_SHM, + .pa = CFG_PUB_RAM_START, .size = SECTION_SIZE, + .cached = true, .secure = false, .rw = true, .exec = false, + }, + + { /* CPU mem map HW registers */ + .type = MEM_AREA_IO_NSEC, + .pa = 0xFFF00000 & ~SECTION_MASK, .size = SECTION_SIZE, + .device = true, .secure = true, .rw = true, + }, + + { /* ASC IP for UART HW tracing */ + .type = MEM_AREA_IO_NSEC, + .pa = (0xFE400000 + 0x00131000) & ~SECTION_MASK, .size = SECTION_SIZE, + .device = true, .secure = false, .rw = true, + }, + + { /* RNG IP for some random support */ + .type = MEM_AREA_IO_SEC, + .pa = (0xFEE80000) & ~SECTION_MASK, .size = SECTION_SIZE, + .device = true, .secure = true, .rw = true, + }, + + {.type = MEM_AREA_NOTYPE} +}; + +/* + * bootcfg_get_pbuf_is_handler - return the platform specfic pbuf_is + */ +unsigned long bootcfg_get_pbuf_is_handler(void) +{ + return (unsigned long)pbuf_is; +} + +/* + * This routine is called while MMU and core memory management are not init. + */ +struct map_area *bootcfg_get_memory(void) +{ + struct map_area *map; + struct memaccess_area *a, *a2; + struct map_area *ret = bootcfg_stih416_memory; + + /* check defined memory access layout */ + a = (struct memaccess_area *)&secure_only; + a2 = (struct memaccess_area *)&nsec_shared; + if (buf_overlaps_area(a->paddr, a->size, a2->paddr, a2->size)) { + EMSG("invalid memory access configuration: sec/nsec"); + ret = NULL; + } + if (ret == NULL) + return ret; + + /* check defined mapping (overlapping will be tested later) */ + map = bootcfg_stih416_memory; + while (map->type != MEM_AREA_NOTYPE) { + switch (map->type) { + case MEM_AREA_TEE_RAM: + a = (struct memaccess_area *)&secure_only; + if (buf_inside_area + (map->pa, map->size, a->paddr, a->size) == false) { + EMSG("TEE_RAM does not fit in secure_only"); + ret = NULL; + } + break; + case MEM_AREA_TA_RAM: + a = (struct memaccess_area *)&secure_only; + if (buf_inside_area + (map->pa, map->size, a->paddr, a->size) == false) { + EMSG("TEE_RAM does not fit in secure_only"); + ret = NULL; + } + break; + case MEM_AREA_NSEC_SHM: + a = (struct memaccess_area *)&nsec_shared; + if (buf_inside_area + (map->pa, map->size, a->paddr, a->size) == false) { + EMSG("TEE_RAM does not fit in secure_only"); + ret = NULL; + } + break; + default: + /* other mapped areas are not checked */ + break; + } + map++; + } + + return ret; +} diff --git a/core/arch/arm32/plat-orly2/core_chip.c b/core/arch/arm32/plat-orly2/core_chip.c new file mode 100644 index 00000000000..6d82709c02d --- /dev/null +++ b/core/arch/arm32/plat-orly2/core_chip.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include + +/* Cut information for Orly2 */ +/* SYSTEM_STATUS2600 = SAS Device ID : + SYSCFGBaseAddress(0xFE830000)+ 0x00000960 */ +/* SYSTEM_STATUS9516 = MPE Device ID : + SYSCFGBaseAddress(0xFD690000)+ 0x00000810 */ +/* [31:28] VERSION: Version + [27:22] GROUP_ID: Group ID + [21:12] DEVICE_ID: Device ID + [11:1] MANUFACTURER_ID: Manufacturer ID + [0] JTAG_BIT: JTAG b */ + +/* SYSTEM_STATUS9516 */ +#define CUT_MPE_MAJOR_ADDR 0xfd690810 +#define CUT_MPE_MAJOR_MASK 0xf0000000 +#define CUT_MPE_MAJOR_SHIFT 28 +#define ORLY2_MPE_MASK 0xFFFFFFFE +#define ORLY2_MPE_VALUE 0x0D44D040 + +/* SYSTEM_STATUS2600 */ +#define CUT_SAS_MAJOR_ADDR 0xfe830960 +#define CUT_SAS_MAJOR_MASK 0xf0000000 +#define CUT_SAS_MAJOR_SHIFT 28 +#define ORLY2_SAS_MASK 0xFFFFFFFE +#define ORLY2_SAS_VALUE 0x0D44C040 + +/* FUSE = MPE SAFMEM : 0xfd6d5000 */ +/* 0x9C: eng_metal_fix_nb<3:0> + * => ST Engineering setting. */ +#define CUT_MPE_MINOR_ADDR 0xfd6d509c +#define CUT_MPE_MINOR_MASK 0xf +#define CUT_MPE_MINOR_SHIFT 0 + +uint32_t tee_get_cutid(void) +{ + uint32_t sas_major = 0, mpe_minor = 0, mpe_major = 0; + uint32_t sas_major_val = 0, mpe_minor_val = 0, mpe_major_val = 0; + uint32_t *sas_major_reg, *mpe_minor_reg, *mpe_major_reg; + uint32_t result; + + /* Map major and minor registers */ + mpe_major_reg = tee_mmu_ioremap(CUT_MPE_MAJOR_ADDR, 4); + sas_major_reg = tee_mmu_ioremap(CUT_SAS_MAJOR_ADDR, 4); + mpe_minor_reg = tee_mmu_ioremap(CUT_MPE_MINOR_ADDR, 4); + + if ((mpe_major_reg != NULL) && + (sas_major_reg != NULL) && (mpe_minor_reg != NULL)) { + mpe_major_val = *mpe_major_reg; + sas_major_val = *sas_major_reg; + mpe_minor_val = *mpe_minor_reg; + + /* Read major revision */ + mpe_major = ((mpe_major_val & CUT_MPE_MAJOR_MASK) >> + CUT_MPE_MAJOR_SHIFT); + + /* Read major revision */ + sas_major = ((sas_major_val & CUT_SAS_MAJOR_MASK) >> + CUT_SAS_MAJOR_SHIFT); + + /* Read minor revision */ + mpe_minor = ((mpe_minor_val & CUT_MPE_MINOR_MASK) >> + CUT_MPE_MINOR_SHIFT); + } + + /* Unmap */ + tee_mmu_iounmap(mpe_major_reg); + tee_mmu_iounmap(sas_major_reg); + tee_mmu_iounmap(mpe_minor_reg); + + DMSG("mpe_major_reg = 0x%x : 0x%x", (unsigned int)mpe_major_reg, + (unsigned int)mpe_major_val); + DMSG("sas_major_reg = 0x%x : 0x%x", (unsigned int)sas_major_reg, + (unsigned int)sas_major_val); + DMSG("mpe_minor_reg = 0x%x : 0x%x", (unsigned int)mpe_minor_reg, + (unsigned int)mpe_minor_val); + + /* Return a hex byte where + * [31:16] is chip name : 0x416 for orly2 + * [15:12] is 0 + * [11: 8] is [A-F] indicating MPE major number + * [ 7: 4] is [A-F] indicating SAS major number, + * [ 3: 0] is [0-9] indicating MPE minor number */ + if ((ORLY2_MPE_VALUE == (mpe_major_val & ORLY2_MPE_MASK)) && + (ORLY2_SAS_VALUE == (sas_major_val & ORLY2_SAS_MASK))) + result = ORLY2_CUTID_VAL + ((mpe_major * 0x100) + + ((sas_major * 0x10) + mpe_minor)); + else + result = 0xFFFFFFFF; + + return result; +} diff --git a/core/arch/arm32/plat-orly2/link.mk b/core/arch/arm32/plat-orly2/link.mk new file mode 100644 index 00000000000..8e7fef233b0 --- /dev/null +++ b/core/arch/arm32/plat-orly2/link.mk @@ -0,0 +1,41 @@ +link-out-dir = $(out-dir)/core/ + +link-script = $(platform-dir)/tz-template.lds +link-script-pp = $(link-out-dir)/tz.lds + +all: $(link-out-dir)tee.elf $(link-out-dir)tee.dmp $(link-out-dir)tee.bin +all: $(link-out-dir)tee.symb_sizes +cleanfiles += $(link-out-dir)tee.elf $(link-out-dir)tee.dmp $(link-out-dir)tee.map +cleanfiles += $(link-out-dir)tee.bin +cleanfiles += $(link-out-dir)tee.symb_sizes +cleanfiles += $(link-script-pp) + +link-ldflags = $(LDFLAGS) +link-ldflags += -T $(link-script-pp) -Map=$(link-out-dir)tee.map +link-ldflags += --sort-section=alignment + +link-ldadd = $(LDADD) +link-ldadd += $(libfiles) +ldargs-tee.elf := $(link-ldflags) $(objs) $(link-ldadd) $(libgcc) + + +$(link-script-pp): $(link-script) $(MAKEFILE_LIST) + @echo PP $< + $(q)sed -e "s/%in_TEE_SCATTER_START%/$(TEE_SCATTER_START)/g" < $< > $@ + + +$(link-out-dir)tee.elf: $(objs) $(libdeps) $(link-script-pp) + @echo LD $@ + $(q)$(LD) $(ldargs-tee.elf) -o $@ + +$(link-out-dir)tee.dmp: $(link-out-dir)tee.elf + @echo OBJDUMP $@ + $(q)$(OBJDUMP) -l -x -d $< > $@ + +$(link-out-dir)tee.bin: $(link-out-dir)tee.elf + @echo OBJCOPY $@ + $(q)$(OBJCOPY) -O binary $< $@ + +$(link-out-dir)tee.symb_sizes: $(link-out-dir)tee.elf + @echo Symb sizes $@ + $(q)$(NM) --print-size --reverse-sort --size-sort $< > $@ diff --git a/core/arch/arm32/plat-orly2/main.c b/core/arch/arm32/plat-orly2/main.c new file mode 100644 index 00000000000..009fb3d79b7 --- /dev/null +++ b/core/arch/arm32/plat-orly2/main.c @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef WITH_STACK_CANARIES +#define STACK_CANARY_SIZE (4 * sizeof(uint32_t)) +#define START_CANARY_VALUE 0xdededede +#define END_CANARY_VALUE 0xabababab +#define GET_START_CANARY(name, stack_num) name[stack_num][0] +#define GET_END_CANARY(name, stack_num) \ + name[stack_num][sizeof(name[stack_num]) / sizeof(uint32_t) - 1] +#else +#define STACK_CANARY_SIZE 0 +#endif + +#define STACK_ALIGNMENT 8 + +#define DECLARE_STACK(name, num_stacks, stack_size) \ + static uint32_t name[num_stacks][(stack_size + STACK_CANARY_SIZE) / \ + sizeof(uint32_t)] \ + __attribute__((section(".bss.prebss.stack"), \ + aligned(STACK_ALIGNMENT))) + +#define GET_STACK(stack) \ + ((vaddr_t)(stack) + sizeof(stack) - STACK_CANARY_SIZE / 2) + + +DECLARE_STACK(stack_tmp, CFG_TEE_CORE_NB_CORE, STACK_TMP_SIZE); +DECLARE_STACK(stack_abt, CFG_TEE_CORE_NB_CORE, STACK_ABT_SIZE); +DECLARE_STACK(stack_sm, CFG_TEE_CORE_NB_CORE, SM_STACK_SIZE); +DECLARE_STACK(stack_thread, NUM_THREADS, STACK_THREAD_SIZE); + +const vaddr_t stack_tmp_top[CFG_TEE_CORE_NB_CORE] = { + GET_STACK(stack_tmp[0]), +#if CFG_TEE_CORE_NB_CORE > 1 + GET_STACK(stack_tmp[1]), +#endif +#if CFG_TEE_CORE_NB_CORE > 2 + GET_STACK(stack_tmp[2]), +#endif +#if CFG_TEE_CORE_NB_CORE > 3 + GET_STACK(stack_tmp[3]), +#endif +#if CFG_TEE_CORE_NB_CORE > 4 +#error "Top of tmp stacks aren't defined for more than 4 CPUS" +#endif +}; + +static void main_fiq(void); +static void main_tee_entry(struct thread_smc_args *args); + +static void init_canaries(void) +{ + size_t n; +#define INIT_CANARY(name) \ + for (n = 0; n < ARRAY_SIZE(name); n++) { \ + uint32_t *start_canary = &GET_START_CANARY(name, n); \ + uint32_t *end_canary = &GET_END_CANARY(name, n); \ + \ + *start_canary = START_CANARY_VALUE; \ + *end_canary = END_CANARY_VALUE; \ + } + + INIT_CANARY(stack_tmp); + INIT_CANARY(stack_abt); + INIT_CANARY(stack_sm); + INIT_CANARY(stack_thread); +} + +void check_canaries(void) +{ +#ifdef WITH_STACK_CANARIES + size_t n; + +#define ASSERT_STACK_CANARIES(name) \ + for (n = 0; n < ARRAY_SIZE(name); n++) { \ + assert(GET_START_CANARY(name, n) == START_CANARY_VALUE);\ + assert(GET_END_CANARY(name, n) == END_CANARY_VALUE); \ + } while (0) + + ASSERT_STACK_CANARIES(stack_tmp); + ASSERT_STACK_CANARIES(stack_abt); + ASSERT_STACK_CANARIES(stack_sm); + ASSERT_STACK_CANARIES(stack_thread); +#endif /*WITH_STACK_CANARIES*/ +} + +static const struct thread_handlers handlers = { + .stdcall = main_tee_entry, + .fastcall = main_tee_entry, + .fiq = main_fiq, + .svc = NULL, /* XXX currently using hardcod svc handler */ + .abort = tee_pager_abort_handler +}; + +void main_init(uint32_t nsec_entry); /* called from assembly only */ +void main_init(uint32_t nsec_entry) +{ + struct sm_nsec_ctx *nsec_ctx; + size_t pos = get_core_pos(); + + /* + * Mask IRQ and FIQ before switch to the thread vector as the + * thread handler requires IRQ and FIQ to be masked while executing + * with the temporary stack. The thread subsystem also asserts that + * IRQ is blocked when using most if its functions. + */ + write_cpsr(read_cpsr() | CPSR_F | CPSR_I); + + if (pos == 0) { + size_t n; + + /* Initialize canries around the stacks */ + init_canaries(); + + /* Assign the thread stacks */ + for (n = 0; n < NUM_THREADS; n++) { + if (!thread_init_stack(n, GET_STACK(stack_thread[n]))) + panic(); + } + } + + if (!thread_init_stack(THREAD_TMP_STACK, GET_STACK(stack_tmp[pos]))) + panic(); + if (!thread_init_stack(THREAD_ABT_STACK, GET_STACK(stack_abt[pos]))) + panic(); + + thread_init_handlers(&handlers); + + /* Initialize secure monitor */ + sm_init(GET_STACK(stack_sm[pos])); + nsec_ctx = sm_get_nsec_ctx(); + nsec_ctx->mon_lr = nsec_entry; + nsec_ctx->mon_spsr = CPSR_MODE_SVC | CPSR_I; +} + +static void main_fiq(void) +{ + panic(); +} + + +static void main_tee_entry(struct thread_smc_args *args) +{ + /* + * This function first catches all ST specific SMC functions + * if none matches, the generic tee_entry is called. + */ + + /* TODO move to main_init() */ + if (init_teecore() != TEE_SUCCESS) + panic(); + + if (args->a0 == TEESMC32_ST_FASTCALL_GET_SHM_CONFIG) { + args->a0 = TEESMC_RETURN_OK; + args->a1 = default_nsec_shm_paddr; + args->a2 = default_nsec_shm_size; + /* Should this be TEESMC cache attributes instead? */ + args->a3 = core_mmu_is_shm_cached(); + return; + } + + if (args->a0 == TEESMC32_ST_FASTCALL_L2CC_MUTEX) { + switch (args->a1) { + case TEESMC_ST_L2CC_MUTEX_GET_ADDR: + case TEESMC_ST_L2CC_MUTEX_SET_ADDR: + case TEESMC_ST_L2CC_MUTEX_ENABLE: + case TEESMC_ST_L2CC_MUTEX_DISABLE: + /* TODO call the appropriate internal functions */ + args->a0 = TEESMC_RETURN_UNKNOWN_FUNCTION; + return; + default: + args->a0 = TEESMC_RETURN_EBADCMD; + return; + } + } + + tee_entry(args); +} + + +/* Override weak function in tee/entry.c */ +void tee_entry_get_api_call_count(struct thread_smc_args *args) +{ + args->a0 = tee_entry_generic_get_api_call_count() + 2; +} + +/* Override weak function in tee/entry.c */ +void tee_entry_get_api_uuid(struct thread_smc_args *args) +{ + args->a0 = TEESMC_ST_UID_R0; + args->a1 = TEESMC_ST_UID_R1; + args->a2 = TEESMC_ST_UID_R2; + args->a3 = TEESMC_ST_UID32_R3; +} + +/* Override weak function in tee/entry.c */ +void tee_entry_get_api_revision(struct thread_smc_args *args) +{ + args->a0 = TEESMC_ST_REVISION_MAJOR; + args->a1 = TEESMC_ST_REVISION_MINOR; +} + +/* Override weak function in tee/entry.c */ +void tee_entry_get_os_uuid(struct thread_smc_args *args) +{ + args->a0 = TEESMC_OS_OPTEE_UUID_R0; + args->a1 = TEESMC_OS_OPTEE_UUID_R1; + args->a2 = TEESMC_OS_OPTEE_UUID_R2; + args->a3 = TEESMC_OS_OPTEE_UUID_R3; +} + +/* Override weak function in tee/entry.c */ +void tee_entry_get_os_revision(struct thread_smc_args *args) +{ + args->a0 = TEESMC_OS_OPTEE_REVISION_MAJOR; + args->a1 = TEESMC_OS_OPTEE_REVISION_MINOR; +} diff --git a/core/arch/arm32/plat-orly2/rng_support.c b/core/arch/arm32/plat-orly2/rng_support.c new file mode 100644 index 00000000000..e3ebe2d8d31 --- /dev/null +++ b/core/arch/arm32/plat-orly2/rng_support.c @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +/* Use the RNG of the HW on this platform */ +#define USE_RNG_HW + +#define USE_FULLY_RNG_HW_IMP 0 +#define USE_SW_DELAY 0 + +/* + * if a HW issue is detected, infinite loop is started until valid data are + * available. + * - User-side timeout is expected to detect the issue. + * else error is logged and 0x00 is returned + */ +#define USE_USER_TIMEOUT 1 + +#ifdef USE_RNG_HW + +/* + * Base address of the RNG on Orly-2, taken from document + * http://wave.st.com/chd/SOC_HW_Design/default.aspx + * SOC HW Design > ORLY > ORLY2_cut1.0 > SoC_Reg_Spec + * top_mpe42.xls + */ +#define RNG_BASE_ADDRESS 0xFEE80000 + +/* Address of the register to read in the RNG IP */ +#define RNG_VAL (RNG_BASE_ADDRESS + 0x24) +#define RNG_STATUS (RNG_BASE_ADDRESS + 0x20) + +static volatile uint32_t *_p_addr_val = (uint32_t *)RNG_VAL; +static volatile uint32_t *_p_addr_status = (uint32_t *)RNG_STATUS; + +static inline int hwrng_waithost_fifo_full(void) +{ + int res = 0; + volatile uint32_t status; + + /* Wait HOST FIFO FULL (see rng_fspec_revG_120720.pdf) */ + do { + status = *_p_addr_status; + } while ((status & 0x20) != 0x20); + + /* Check STATUS (see rng_fspec_revG_120720.pdf) */ + if ((status & 0x3) != 0) { + EMSG("generated HW random data are not valid"); + res = -1; + } + +#if (USE_USER_TIMEOUT == 1) + if (res != 0) + while (1) + ; +#endif + + return res; +} + +uint8_t hw_get_random_byte(void) +#if (USE_FULLY_RNG_HW_IMP == 1) +{ + /* + * Only the HW RNG IP is used to generate the value through the + * HOST interface. + * + * @see the document rng_fspec_revG_120720.pdf for details + * + * - HOST FIFO size = 8x8b (64b) + * - LSB (16b) of the RNG_VAL register allows to read 16b + * - bit5 of the RNG_STATUS register allows to known if the HOST + * FIFO is full or not. + * - bit1,0 of the RNG_STATUS register allows to known if the + * data are valid. + * + * Main principle: + * For performance reason, a local SW fifo is used to store the + * content of the HOST FIFO (max size = 8bytes). When a random + * value is expected, this SW fifo is used to return a stored value. + * When the local SW fifo is empty, it is filled with the HOST FIFO + * according the following sequence: + * + * - wait HOST FIFO full + * o Indicates that max 8-bytes (64b) are available + * o This is mandatory to guarantee that a valid data is + * available. No STATUS bit to indicate that the HOST FIFO + * is empty is provided. + * - check STATUS bits + * - update the local SW fifo with the HOST FIFO + * + * This avoid to wait at each iteration that a valid random value is + * available. _LOCAL_FIFO_SIZE indicates the size of the local SW fifo. + * + */ + + +#define _LOCAL_FIFO_SIZE 8 /* min 2, 4, 6, max 8 */ + + static uint8_t lfifo[_LOCAL_FIFO_SIZE]; /* local fifo */ + static int pos = -1; + + static int nbcall; /* debug purpose - 0 is the initial value*/ + + volatile uint32_t tmpval[_LOCAL_FIFO_SIZE/2]; + uint8_t value; + int i; + int res; + + nbcall++; + + /* Retrieve data from local fifo */ + if (pos >= 0) { + pos++; + value = lfifo[pos]; + if (pos == (_LOCAL_FIFO_SIZE - 1)) + pos = -1; + return value; + } + + /* Wait HOST FIFO full */ + res = hwrng_waithost_fifo_full(); + if (res < 0) + return 0x00; + + /* Read the FIFO according the number of expected element */ + for (i = 0; i < _LOCAL_FIFO_SIZE / 2; i++) { + tmpval[i] = *_p_addr_val & 0xFFFF; +#if (USE_SW_DELAY == 1) + /* Wait 0.667 us (fcpu = 600Mhz -> 400 cycles) @see doc */ + volatile int ll = 200; + while (ll--) + ; +#endif + } + /* Update the local SW fifo for next request */ + pos = 0; + for (i = 0; i < _LOCAL_FIFO_SIZE / 2; i++) { + lfifo[pos] = tmpval[i] & 0xFF; + pos++; + lfifo[pos] = (tmpval[i] >> 8) & 0xFF; + pos++; + }; + + pos = 0; + return lfifo[pos]; +} +#else /* USE_FULLY_RNG_HW_IMP != 1 */ +{ + /* + * The HW RNG IP is used to generate a seed periodically + * (MAX_SOFT_RNG) through the HOST interface. + * + * @see the document rng_fspec_revG_120720.pdf for details + * + * - Pseudo SW Random generator is used to generate the random + * value. + */ + + static uint32_t _lcg_state; + static uint32_t _nb_soft; /* 0 is the initial value */ + int res; + +#define MAX_SOFT_RNG 512 + + static const uint32_t _a = 1664525; + static const uint32_t _c = 1013904223; + + if (_nb_soft == 0) { + /* Update the seed as a "real" HW random generated number */ + do { + res = hwrng_waithost_fifo_full(); + if (res < 0) + return 0x00; + _lcg_state = *_p_addr_val & 0xFFFF; + _lcg_state <<= 16; + +#if (USE_SW_DELAY == 1) + /* + * Wait 0.667 us (fcpu = 600Mhz -> 400 cycles) + * @see doc + */ + volatile int ll = 200; + while (ll--) + ; +#endif + _lcg_state |= *_p_addr_val & 0xFFFF; + } while (_lcg_state == 0); + } + _nb_soft = (_nb_soft + 1) % MAX_SOFT_RNG; + _lcg_state = (_a * _lcg_state + _c); + + return (uint8_t) (_lcg_state >> 24); +} +#endif + +#else +/* Software version. Comes from the compiler */ +uint8_t hw_get_random_byte(void) +{ + static uint8_t value = 1; + static uint32_t ite; /* 0 is the initial value */ + + ite++; + srand(ite); + value = (256 * ((double)rand() / RAND_MAX)); + /* AMSG("SW Random value = 0x%02x", value); */ + return value; +} + +#endif + diff --git a/core/arch/arm32/plat-orly2/sub.mk b/core/arch/arm32/plat-orly2/sub.mk new file mode 100644 index 00000000000..b177fa460cd --- /dev/null +++ b/core/arch/arm32/plat-orly2/sub.mk @@ -0,0 +1,17 @@ +srcs-y += tee_common_otp.c +cflags-tee_common_otp.c-y += -Wno-unused-parameter + +srcs-y += core_bootcfg.c +srcs-y += core_chip.c +srcs-y += rng_support.c + +srcs-y += asc.S +srcs-y += tz_a9init.S +srcs-y += main.c + +srcs-y += tz_sinit.S +aflags-tz_sinit.S-y += \ + -Xassembler --defsym \ + -Xassembler STM_SECONDARY_STARTUP=$(SECONDARY_STARTUP_PHYS) \ + -Xassembler --defsym \ + -Xassembler STEXT=$(PRIMARY_STARTUP_PHYS) diff --git a/core/arch/arm32/plat-orly2/system_config.in b/core/arch/arm32/plat-orly2/system_config.in new file mode 100644 index 00000000000..00302fc96ec --- /dev/null +++ b/core/arch/arm32/plat-orly2/system_config.in @@ -0,0 +1,40 @@ +# this script defines platform specficis settings for TEE armv7 build + +DDR_PHYS_START := 0x40000000 +DDR_SIZE := 0x40000000 + +DDR1_PHYS_START := 0x80000000 +DDR1_SIZE := 0x40000000 + + +# Hard coded NB cores +CFG_TEE_CORE_NB_CORE := 2 + +# Static configuration of DDR reserved to TEE/TZ +# Provide here only start address and size. TEEcore will adapt. +# Allow these settings to be overridden. +CFG_DDR_TEETZ_RESERVED_START ?= 0xBF800000 +CFG_DDR_TEETZ_RESERVED_SIZE ?= 0x00800000 + +TEE_SCATTER_START := $(CFG_DDR_TEETZ_RESERVED_START) + + +# Plaform/Project/Board specfic static configuration +# +ifeq ($(BUILD_FOR_ANDROID),true) + +# STDroid setup +LINUX_PAGE_OFFSET := 0x80000000 +LINUX_LOAD_ADDR := 0x70000000 + +else + +# SDK2 setup +LINUX_PAGE_OFFSET := 0x40000000 +LINUX_LOAD_ADDR := 0x40000000 + +endif + +STACK_TMP_SIZE := 1024 # TODO minimize +STACK_ABT_SIZE := 1024 +STACK_THREAD_SIZE := 8192 diff --git a/core/arch/arm32/plat-orly2/tee_common_otp.c b/core/arch/arm32/plat-orly2/tee_common_otp.c new file mode 100644 index 00000000000..9b4705daa79 --- /dev/null +++ b/core/arch/arm32/plat-orly2/tee_common_otp.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#define SHA256_HASH_SIZE 32 +uint8_t hw_key_digest[SHA256_HASH_SIZE]; + +/*---------------------------------------------------------------------------*/ +/* tee_otp_get_hw_unique_key */ +/*---------------------------------------------------------------------------*/ +/* + This function reads out a hw unique key. + + \param[in] hwkey data place holder for the key data read + \param[out] None. + \return None. + + */ +/*---------------------------------------------------------------------------*/ +void tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) +{ + /* Copy the first part of the new hw key */ + memcpy(&hwkey->data[0], &hw_key_digest[0], + sizeof(struct tee_hw_unique_key)); +} + +int tee_otp_get_die_id(uint8_t *buffer, size_t len) +{ + size_t i; + + char pattern[4] = { 'B', 'E', 'E', 'F' }; + for (i = 0; i < len; i++) + buffer[i] = pattern[i % 4]; + + return 0; +} diff --git a/core/arch/arm32/plat-orly2/tz-template.lds b/core/arch/arm32/plat-orly2/tz-template.lds new file mode 100644 index 00000000000..ac49b0df8c4 --- /dev/null +++ b/core/arch/arm32/plat-orly2/tz-template.lds @@ -0,0 +1,62 @@ +OUTPUT_ARCH(arm) +ENTRY(tz_sinit) + +MEMORY +{ + /* 1 MByte is allocated for teecore execution */ + EXEC_MEM (rw) : ORIGIN = (%in_TEE_SCATTER_START% + 0x00000000), LENGTH = 0x000D0000 + STACKS_MEM (rw) : ORIGIN = (%in_TEE_SCATTER_START% + 0x000D0000), LENGTH = 0x00010000 + CTX_MEM (rw) : ORIGIN = (%in_TEE_SCATTER_START% + 0x000E0000), LENGTH = 0x00010000 + MMU_MEM (rw) : ORIGIN = (%in_TEE_SCATTER_START% + 0x000F0000), LENGTH = 0x00010000 +} + +SECTIONS +{ + .teecore_exec : + { + *(.vector_table) + *(.text); *(.text.*) + *(.rodata); *(.rodata.*) + *(.got); *(.got.*) + *(.data); *(.data.*) + + __start_ta_head_section = . ; + *(ta_head_section) + __stop_ta_head_section = . ; + + __bss_start = (.) ; + *(.bss) + __bss_end = (.) ; + + *(COMMON) + + } > EXEC_MEM + + .stacks : + { + __stacks_start = (.); + *(.bss.prebss.stack) + } > STACKS_MEM + + /* NSec and Secure context storage (TODO: move in C-code) */ + .context_backup : + { + PUB_CONTEXT_BACKUP = (. + 0x000); /* Public context backup area */ + SEC_CONTEXT_BACKUP = (. + 0x400); /* Secure context backup area */ + } > CTX_MEM + + /* MMU pages tables (TODO: should we keep them cachable?) */ + .pagestables : + { + SEC_MMU_TTB_FLD = (.); /* MMU L1 table for teecore: 16kB */ + SEC_MMU_TTB_SLD = (. + 0x4000); /* MMU L2 tables for teecore: 16*1kB (16MB mappeable) */ + SEC_TA_MMU_TTB_FLD = (. + 0x8000); /* MMU L1 table for TAs: 16kB */ + SEC_TA_MMU_TTB_SLD = (. + 0xC000); /* MMU L2 tables for TAs:: 16*1kB (16MB mappeable) */ + SEC_MMU_TTB_END = (. + 0x10000); /* end of teecore and TAs MMU tables */ + } > MMU_MEM +} + + /* 64kB aligned heap start between BSS and secure stacks */ + PROVIDE(teecore_heap_start = __bss_end); + PROVIDE(teecore_heap_end = __stacks_start); + diff --git a/core/arch/arm32/plat-orly2/tz_a9init.S b/core/arch/arm32/plat-orly2/tz_a9init.S new file mode 100644 index 00000000000..1dad99c787e --- /dev/null +++ b/core/arch/arm32/plat-orly2/tz_a9init.S @@ -0,0 +1,425 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Entry points for the A9 inits, A9 revision specific or not. + * It is assume no stack is available when these routines are called. + * It is assume each routine is called with return address in LR + * and with ARM registers R0, R1, R2, R3 being scratchable. + */ + +.global arm_secboot_identify_cpu +.global arm_secboot_early +.global arm_secboot_errata +.global arm_cl2_config +.global arm_cl2_enable +.global arm_secboot_late + +#define CPUID_A9_R2P2_H 0x412f +#define CPUID_A9_R2P2_L 0xc092 + +#define CPUID_A9_R3P0_H 0x413f +#define CPUID_A9_R3P0_L 0xc090 + +.section .text +.balign 4 +.code 32 + +/* + * arm_secboot_identify_cpu - identify and save CPU version + * + * Use scratables registers R0-R3. + * No stack usage. + * LR store return address. + * Trap CPU in case of error. + */ +.func arm_secboot_identify_cpu +arm_secboot_identify_cpu: + + mrc p15, 0, r0, c0, c0, 0 /* read A9 ID */ + movw r1, #CPUID_A9_R2P2_L + movt r1, #CPUID_A9_R2P2_H + cmp r0, r1 + beq _ident_a9_r2p2 + movw r1, #CPUID_A9_R3P0_L + movt r1, #CPUID_A9_R3P0_H + cmp r0, r1 + beq _ident_a9_r3p0 + b . /* TODO: unknown id: reset? log? */ + +_ident_a9_r2p2: + /* unsupported version. TODO: needs to be supported */ + b . /* TODO: unknown id: reset? log? */ + +_ident_a9_r3p0: + mov pc, lr /* back to tzinit */ + +.endfunc + +/* + * Memory Cache Level2 Configuration Function + * + * Use scratables registers R0-R3. + * No stack usage. + * LR store return address. + * Trap CPU in case of error. + */ +.func arm_cl2_config +arm_cl2_config: + + mrc p15, 0, r0, c0, c0, 0 /* read A9 ID */ + movw r1, #CPUID_A9_R3P0_L + movt r1, #CPUID_A9_R3P0_H + cmp r0, r1 + beq _config_l2cc_r3p0 + b . /* TODO: unknown id: reset? log? */ + +_config_l2cc_r3p0: + /* + * reg1_tag_ram_control (cache_l2x0.c) + * bit[10:8]:1 - 2 cycle of write accesses latency + * bit[6:4]:1 - 2 cycle of read accesses latency + * bit[2:0]:1 - 2 cycle of setup latency + */ + movw r0, #0x2108 + movt r0, #0xFFFE + ldr r2, [r0] + movw r1, #0xf888 + movt r1, #0xffff + and r2,r2,r1 + movw r1, #0xf999 + movt r1, #0xffff + orr r2,r2,r1 + str r2, [r0] + + /* + * reg1_data_ram_control (cache_l2x0.c) + * bit[10:8]:2 - 3 cycle of write accesses latency + * bit[6:4]:2 - 3 cycle of read accesses latency + * bit[2:0]:2 - 3 cycle of setup latency + */ + movw r0, #0x210C + movt r0, #0xFFFE + ldr r2, [r0] + movw r1, #0xf888 + movt r1, #0xffff + and r2,r2,r1 + movw r1, #0xfaaa + movt r1, #0xffff + orr r2,r2,r1 + str r2, [r0] + + /* + * reg1_aux_control + */ + movw r0, #0x2104 + movt r0, #0xFFFE + movw r1, #0x0801 + movt r1, #0x3C48 + str r1, [r0] + + /* + * reg15_prefetch_ctrl + */ + movw r0, #0x2F60 + movt r0, #0xFFFE + movw r1, #0x0000 + movt r1, #0x3100 + str r1, [r0] + + /* + * reg15_power_ctrl + */ + movw r0, #0x2F80 + movt r0, #0xFFFE + movw r1, #0x0003 + movt r1, #0x0000 + str r1, [r0] + + /* invalidate all cache ways PL310_BASE + invalidate by way offset = 0xFFFE2000 + 0x77C) */ + movw r0, #0x277C + movt r0, #0xFFFE + movw r1, #0x00FF + movt r1, #0x0000 + str r1, [r0] + + mov pc, lr + +.endfunc +/* End of arm_cl2_config */ + + +/* + * Memory Cache Level2 Enable Function + * + * Use scratables registers R0-R3. + * No stack usage. + * LR store return address. + * Trap CPU in case of error. + */ +.func arm_cl2_enable +arm_cl2_enable: + + /* Enable L2 ctrl (PL310_BASE + L2x0_CTRL = 0xFFFE2000 + 0x100) --> only set lsb bit */ + movw r0, #0x2100 + movt r0, #0xFFFE + movw r1, #0x0001 + movt r1, #0x0000 + str r1, [r0] + + mov pc, lr + +.endfunc +/* End of arm_cl2_enable */ + +/* + * Cortex A9 configuration early configuration + * + * Use scratables registers R0-R3. + * No stack usage. + * LR store return address. + * Trap CPU in case of error. + */ +.func arm_secboot_early +arm_secboot_early: + + /* only r3p0 is supported */ + mrc p15, 0, r0, c0, c0, 0 /* read A9 ID */ + movw r1, #CPUID_A9_R3P0_L + movt r1, #CPUID_A9_R3P0_H + cmp r0, r1 + beq _early_a9_r3p0 + b . /* TODO: unknown id: reset? log? */ + +_early_a9_r3p0: + /* + * Register SCTLR + * RR Bit[14]=1 + */ + movw r0, #0x4000 + movt r0, #0x0000 + mcr p15, 0, r0, c1, c0, 0 + + /* + * Register ACTLR + * FW Bit[0]=1 + * WFLZ Bit[3]=1 + * SMP Bit[6]=1 + */ + movw r0, #0x0049 + movt r0, #0x0000 + mcr p15, 0, r0, c1, c0, 1 + + /* + * Register NSACR + * TL Bit[17]=1 + * CPU11 Bit[11]=1 + * CPU10 Bit[10]=1 + */ + movw r0, #0x0C00 + movt r0, #0x0002 + mcr p15, 0, r0, c1, c1, 2 + + /* + * Register PCR + * ECG Bit[0]=1 + */ + movw r0, #0x0000 + movt r0, #0x0001 + mcr p15, 0, r0, c15, c0, 0 + + /* + * GIC configuration + */ + /* + * Register ICDISR0 + */ + movw r0, #0x1080 + movt r0, #0xFFFE + mov r1, #0xFFFFFFFF + str r1, [r0] + + /* + * Register ICCPMR + */ + movw r0, #0x0104 + movt r0, #0xFFFE + mov r1, #0xFFFFFFFF + str r1, [r0] + + mov pc, lr /* back to tzinit */ + +.endfunc + +/* + * arm_secboot_errata - arm errata, specific per core revision + * + * Use scratables registers R0-R3. + * No stack usage. + * LR store return address. + * Trap CPU in case of error. + */ +.func arm_secboot_errata +arm_secboot_errata: + + mrc p15, 0, r0, c0, c0, 0 /* read A9 ID */ + movw r1, #CPUID_A9_R2P2_L + movt r1, #CPUID_A9_R2P2_H + cmp r0, r1 + beq _errata_a9_r2p2 + movw r1, #CPUID_A9_R3P0_L + movt r1, #CPUID_A9_R3P0_H + cmp r0, r1 + beq _errata_a9_r3p0 + b . /* TODO: unknown id: reset? log? */ + +_errata_a9_r2p2: + /* unsupported version. TODO: needs to be supported */ + b . /* TODO: unknown id: reset? log? */ + +_errata_a9_r3p0: + mov pc, lr + +.endfunc + +/* + * A9 secured config, needed only from a single core + * + * Use scratables registers R0-R3. + * No stack usage. + * LR store return address. + * Trap CPU in case of error. + */ +.func arm_secboot_late +arm_secboot_late: + + /* + * Snoop Control Unit configuration + * + * SCU is enabled with filtering off. + * Both Secure/Unsecure can access SCU and timers + * + * 0x00 SCUControl = 0x00000060 !!! should be 0x5 ! A NETTOYER !!!!!!!!!!!!!!!!!!!!!!!!! + * 0x04 SCUConfiguration = ??? A NETTOYER !!!!!!!!!!!!!!!!!!!!!!!!! + * 0x0C SCUInvalidateAll (Secure cfg) + * 0x40 FilteringStartAddress = 0x40000000 + * 0x44 FilteeringEndAddress - 0x80000000 + * 0x50 SCUAccessControl + * 0x54 SCUSecureAccessControl + */ + + /* + * Register SAC: both secure CPU access SCU + */ + movw r0, #0x0050 /* LSB */ + movt r0, #0xFFFE /* MSB */ + movw r1, #0x0003 + movt r1, #0x0000 + str r1, [r0] + + /* + * Register SNSAC: both nonsec cpu access SCU, private and global timer + */ + movw r0, #0x0054 /* LSB */ + movt r0, #0xFFFE /* MSB */ + movw r1, #0x0333 + movt r1, #0x0000 + str r1, [r0] + + /* + * Register SFEA + */ + movw r0, #0x0044 /* LSB */ + movt r0, #0xFFFE /* MSB */ + movw r1, #0x0000 + movt r1, #0x8000 + str r1, [r0] + + /* + * Register SFSA + */ + movw r0, #0x0040 /* LSB */ + movt r0, #0xFFFE /* MSB */ + movw r1, #0x0000 + movt r1, #0x4000 + str r1, [r0] + + /* + * Register SCU_CTRL + */ + movw r0, #0x0000 /* LSB */ + movt r0, #0xFFFE /* MSB */ + movw r1, #0x0065 + movt r1, #0x0000 + str r1, [r0] + + /*- GIC secure configuration ---*/ + + /* + * Register ICDISR[0-31] + */ + movw r0, #0x1084 + movt r0, #0xFFFE + mov r2, #0xFFFFFFFF + mov r1, #31 /* Nb of loop rounds */ +loop_1: + str r2, [r0] + add r0, #4 + sub r1, r1, #1 + cmp r1, #0 + bne loop_1 + + + /*- L2 Memory Controller (Note: should be done with NS=1) ---*/ + + /* + * reg12_addr_filtering_end + */ + movw r0, #0x2C04 + movt r0, #0xFFFE + movw r1, #0x0000 + movt r1, #0x8000 + str r1, [r0] + + /* + * reg12_addr_filtering_start + */ + movw r0, #0x2C00 + movt r0, #0xFFFE + movw r1, #0x0001 + movt r1, #0x4000 + str r1, [r0] + + /* Allow NSec to manage FIQ/Imprecise abort */ + mrc p15, 0, r0, c1, c1, 0 /* read Secure Configuration Register */ + orr r0, r0, #0x30 /* SCR[FW]=1, SCR[AW]=1 */ + mcr p15, 0, r0, c1, c1, 0 /* write updated value in Secure Configuration Register */ + + mov pc, lr + +.endfunc + diff --git a/core/arch/arm32/plat-orly2/tz_sinit.S b/core/arch/arm32/plat-orly2/tz_sinit.S new file mode 100644 index 00000000000..f25b675995a --- /dev/null +++ b/core/arch/arm32/plat-orly2/tz_sinit.S @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Include(s) + */ +#include +#include + +/* + * Booting on 1 or 2 cores ? + * - currently teecore boot on both cores. It expected 2 cores and synchronise + * between the 2 cores execution during boot sequence, mainly to enable + * mmu and cache in a coherent way. + * + * - If FORCE_UNIPROC is set (internal switch, below), once both core are + * booted, only the primary CPU will branch to the next boot stage. + */ + +/* + * Booting linux + * ------------- + * + * Current tz init routine is designed to init Secure Mode/Monitor, switch to + * NSec world and boot a linux kernel image pre-loaded in RAM. + * + * 1) jumping into linux entries + * + * physical address of linux entry routine = + * virtual address of the linux entry routine read from vmlinux + * - linux configuration value for CONFIG_PAGE_OFFSET + * + physical address where linux is loaded by bootloader or GDB + * + * PRIMARY_STARTUP_PHYS is set by build env and defines linux boot CPU physical entry. + * SECONDARY_STARTUP_PHYS is set by build env and defines linux econdary CPUs + * entry physical address. + * + * 2) linux boot arguments (CONFIG_TEE_GDB_BOOT) + * + * In current setup (GDB boot), when here, DDR is ready, linux and tee images + * are loaded in DDR, linux boot arguments are stored in DDR. CPU0 register + * R0 = 0, R1 = linux machine ID, R2 = devtree/atags address. + * + * Since the current GDB boot, the content of registers R0, R1, and R2 should + * be preserved (backed-up) for restore once Secure inits are done and CPUs + * jump to linux kernel entry in Nsec mode. + * To do so, save R0/R1/R2 to R10/R11/R12, which are preserved by all + * execution code until a stack is setup for the inits, for CPU0. + */ + +/* Image */ +.equ stext, STEXT +.equ stm_secondary_startup, STM_SECONDARY_STARTUP + +/* Global Functions */ +.global tz_sinit + + +/* + * Semaphore to let primary CPU runs its inits + * before secondary CPUs run their own inits + */ +.equ SEM_NOT_READY, 2 +.equ SEM_CPU0_READY, 4 +.equ SEM_CPU1_READY, 8 + +.section .data +.balign 4 + +sem_cpu_sync: + .word SEM_NOT_READY; + +#ifdef CONFIG_TEE_GDB_BOOT +gdb_bootargs: + .word 0 + .word 0 + .word 0 + .word 0 +#endif + + .section .vector_table + .align 5 + .code 32 + +initial_vector: + b tz_sinit + b . /* Undef */ + b . /* Syscall */ + b . /* Prefetch abort */ + b . /* Data abort */ + b . /* Reserved */ + b . /* IRQ */ + b . /* FIQ */ + +/* + * Vector Table Initialization Function + * + * Use scratables registers R0-R3. + * No stack usage. stack is setup by this routine + * LR store return address. + */ +.section .text +.code 32 +.balign 4 + +secure_init_vector_table: + /* Set initial vector table base registers (VBAR and MVBAR) */ + ldr r0, =initial_vector + + /* write VBAR (Secure Mode Vector Base Address Register) */ + mcr p15, 0, r0, c12, c0, 0 + + /* write MVBAR (Monitor Vector Base Address Register) */ + mcr p15, 0, r0, c12, c0, 1 + + bx lr +/* End of secure_init_vector_table */ + + +/* + * TrustZone Initialization Function + */ +.section .text +.code 32 +.balign 4 + +tz_sinit: + +#ifdef CONFIG_TEE_GDB_BOOT + /* boot preloaded linux: save linux boot args from GDB */ + mov r10, r0 + mov r11, r1 + mov r12, r2 + /* all following routines, until stack is setup, preserve R10/R11/R12 */ +#endif + + /* + * Primary CPU and secondary CPUs internal initialization + */ + bl arm_secboot_identify_cpu + bl arm_secboot_early + bl arm_secboot_errata + bl secure_init_vector_table + + /* Setup tmp stack */ + bl get_core_pos + lsl r0, #2 + ldr r1, =stack_tmp_top + ldr sp, [r1, r0] + + /* + * Case Primary CPU: proceed common cfg + * Case secondary CPUs: wait CPU0 is done + */ + bl secure_get_cpu_id + cmp r0, #CPU_ID0 + bne _BootCPU1 + +_BootCPU0: + + /* complete ARM secure MP common configuration */ + bl arm_secboot_late + +#ifdef CONFIG_TEE_GDB_BOOT + ldr r0, =gdb_bootargs + str r10, [r0, #0] + str r11, [r0, #4] + str r12, [r0, #8] +#endif + + /* Cache/MMU Initialization */ + bl arm_cl2_config + bl arm_cl1_d_invbysetway + bl arm_cl2_invbyway + bl arm_cl2_enable + + bl secure_mmu_init + bl mmu_enable + bl mmu_enable_icache + bl mmu_enable_dcache + + /* init BSS */ +init_bss: + ldr r0, =__bss_start + ldr r2, =__bss_end + sub r2, r2, r0 + ldr r1, =0 + bl memset + + /* Initialize thread handling and secure monitor */ + ldr r0, =stext + bl main_init + + /* release secondary CPUs */ + ldr r0,=sem_cpu_sync + ldr r1, =SEM_CPU0_READY + str r1, [r0] + dsb + + /* Flush all caches before secondary CPUs setup */ + bl arm_cl1_d_cleaninvbysetway + bl arm_cl2_cleaninvbyway + bl arm_cl1_d_cleaninvbysetway + + sev + + /* Primary CPU waits secondary */ + ldr r0,=sem_cpu_sync + mov r2, #SEM_CPU1_READY +_wait_cpu1: + ldr r1, [r0] + cmp r1, r2 + wfene + bne _wait_cpu1 + + /* TODO: call teecore inits */ + + /* ask monitor to enter NSec from TEE boot sequence */ +#ifdef CONFIG_TEE_GDB_BOOT + /* restore linux boot arguments */ + ldr r4, =gdb_bootargs + ldr r0, [r4, #0] + ldr r1, [r4, #4] + ldr r2, [r4, #8] +#endif + + smc #0 + b thread_recv_smc_call + +_BootCPU1: + + /* secondary CPUs wait that primary boot CPU have made the MMU/bss inits */ + ldr r0,=sem_cpu_sync + mov r2, #SEM_CPU0_READY +_wait_cpu0: + ldr r1, [r0] + cmp r1, r2 + wfene + bne _wait_cpu0 + + bl arm_cl1_d_cleaninvbysetway + bl arm_cl2_cleaninvbyway + + bl secure_mmu_init + bl mmu_enable + + bl mmu_enable_icache + bl mmu_enable_dcache + + /* syncrhonise with CPU0 */ + ldr r0,=sem_cpu_sync + ldr r1, =SEM_CPU1_READY + str r1, [r0] + dsb + sev + + /* Comment out next line to force booting NSec on 1 core only */ +//#define FORCE_UNIPROC +#ifdef FORCE_UNIPROC + b . +#endif + + /* Initialize thread handling and secure monitor */ + ldr r0, =stm_secondary_startup + bl main_init + + smc #0 + b thread_recv_smc_call + +/* End of tz_sinit */ diff --git a/core/arch/arm32/sm/sm.c b/core/arch/arm32/sm/sm.c new file mode 100644 index 00000000000..835fa2fb951 --- /dev/null +++ b/core/arch/arm32/sm/sm.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include + +#include + + +static struct sm_nsec_ctx sm_nsec_ctx[CFG_TEE_CORE_NB_CORE]; +static struct sm_sec_ctx sm_sec_ctx[CFG_TEE_CORE_NB_CORE]; + +struct sm_nsec_ctx *sm_get_nsec_ctx(void) +{ + return &sm_nsec_ctx[get_core_pos()]; +} + +struct sm_sec_ctx *sm_get_sec_ctx(void) +{ + return &sm_sec_ctx[get_core_pos()]; +} diff --git a/core/arch/arm32/sm/sm_asm.S b/core/arch/arm32/sm/sm_asm.S new file mode 100644 index 00000000000..6747159e8a0 --- /dev/null +++ b/core/arch/arm32/sm/sm_asm.S @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +LOCAL_FUNC sm_save_modes_regs , : + /* User mode registers has to be saved from system mode */ + cps #CPSR_MODE_SYS + stm r0!, {sp, lr} + + cps #CPSR_MODE_IRQ + mrs r2, spsr + stm r0!, {r2, sp, lr} + + cps #CPSR_MODE_SVC + mrs r2, spsr + stm r0!, {r2, sp, lr} + + cps #CPSR_MODE_ABT + mrs r2, spsr + stm r0!, {r2, sp, lr} + + cps #CPSR_MODE_UND + mrs r2, spsr + stm r0!, {r2, sp, lr} + + cps #CPSR_MODE_MON + ldm r1, {r2-r3} /* Load SPSR and LR from the stack */ + stm r0!, {r2-r3} /* Store SPSR and LR in context */ + bx lr +END_FUNC sm_save_modes_regs + +/* Restores the mode specific registers */ +LOCAL_FUNC sm_restore_modes_regs , : + /* User mode registers has to be saved from system mode */ + cps #CPSR_MODE_SYS + ldm r0!, {sp, lr} + + cps #CPSR_MODE_IRQ + ldm r0!, {r2, sp, lr} + msr spsr, r2 + + cps #CPSR_MODE_SVC + ldm r0!, {r2, sp, lr} + msr spsr, r2 + + cps #CPSR_MODE_ABT + ldm r0!, {r2, sp, lr} + msr spsr, r2 + + cps #CPSR_MODE_UND + ldm r0!, {r2, sp, lr} + msr spsr, r2 + + cps #CPSR_MODE_MON + ldm r0!, {r2-r3} /* Load SPSR and LR from context */ + stm r1, {r2-r3} /* Store SPSR and LR in stack */ + bx lr +END_FUNC sm_restore_modes_regs + +LOCAL_FUNC sm_smc_entry , : + srsdb sp!, #CPSR_MODE_MON + push {r0-r3} +/* Positions relative to stack pointer */ +#define SMC_ENTRY_R0R3_OFFS 0 +#define SMC_ENTRY_SRS_OFFS (4 * 4 + SMC_ENTRY_R0R3_OFFS) + + /* Clear the exclusive monitor */ + clrex + + /* Find out if we're doing an secure or non-secure entry */ + read_scr r1 + tst r1, #SCR_NS + bne .smc_ret_to_sec + +.smc_ret_to_nsec: + /* Save secure context */ + bl sm_get_sec_ctx + add r1, sp, #SMC_ENTRY_SRS_OFFS /* Where srsdb wrote */ + bl sm_save_modes_regs + + /* Restore non-secure context */ + bl sm_get_nsec_ctx + add r1, sp, #SMC_ENTRY_SRS_OFFS /* Where srsdb wrote */ + bl sm_restore_modes_regs + ldm r0!, {r4-r12} + + /* Update SCR */ + read_scr r0 + orr r0, r0, #(SCR_NS | SCR_FIQ) /* Set NS and FIQ bit in SCR */ + write_scr r0 + + b .smc_exit + +.smc_ret_to_sec: + bic r1, r1, #(SCR_NS | SCR_FIQ)/* Clear NS and FIQ bit in SCR */ + write_scr r1 + + /* Save non-secure context */ + push {r12, lr} + bl sm_get_nsec_ctx + pop {r12, lr} + add r1, sp, #SMC_ENTRY_SRS_OFFS /* Where srsdb wrote */ + bl sm_save_modes_regs + stm r0!, {r4-r12} + + /* Restore secure context */ + bl sm_get_sec_ctx + add r1, sp, #SMC_ENTRY_SRS_OFFS /* Where srsdb wrote */ + bl sm_restore_modes_regs + +.smc_exit: + pop {r0-r3} + rfefd sp! +END_FUNC sm_smc_entry + +/* + * FIQ handling + * + * Saves CPU context in per core structure sm_pre_fiq_ctx which + * later will be restored in the smc handler when handling a return + * from FIQ. + */ +LOCAL_FUNC sm_fiq_entry , : + /* FIQ has a +4 offset for lr compared to preferred return address */ + sub lr, lr, #4 + srsdb sp!, #CPSR_MODE_MON + push {r0-r3} +/* Positions relative to stack pointer */ +#define FIQ_ENTRY_R0R3_OFFS 0 +#define FIQ_ENTRY_SRS_OFFS (4 * 4 + SMC_ENTRY_R0R3_OFFS) + + /* Update SCR */ + read_scr r1 + bic r1, r1, #(SCR_NS | SCR_FIQ) /* Set NS and FIQ bit in SCR */ + write_scr r1 + + /* Save non-secure context */ + push {r12, lr} + bl sm_get_nsec_ctx + pop {r12, lr} + add r1, sp, #FIQ_ENTRY_SRS_OFFS /* Where srsdb wrote */ + bl sm_save_modes_regs + stm r0!, {r4-r12} + + /* Restore secure context */ + bl sm_get_sec_ctx + add r1, sp, #FIQ_ENTRY_SRS_OFFS /* Where srsdb wrote */ + bl sm_restore_modes_regs + + /* + * FIQ handling (return from TEESMC_CALL_HANDLE_FIQ) has to return + * supplied R1-R4 in R0-R3 since R0-R3 aren't saved anywhere else. + */ + pop {r1-r4} /* R0-R3 pushed at entry */ + ldr r0, =TEESMC32_CALL_HANDLE_FIQ /* Let Trusted OS handle FIQ */ + + rfefd sp! +END_FUNC sm_fiq_entry + + .align 5 +LOCAL_FUNC sm_vect_table , : + b . /* Reset */ + b . /* Undefined instruction */ + b sm_smc_entry /* Secure monitor call */ + b . /* Prefetch abort */ + b . /* Data abort */ + b . /* Reserved */ + b . /* IRQ */ + b sm_fiq_entry /* FIQ */ +END_FUNC sm_vect_table + +/* void sm_init(vaddr_t stack_pointer); */ +FUNC sm_init , : + push {r0, lr} + + /* Set monitor stack */ + mrs r1, cpsr + cps #CPSR_MODE_MON + mov sp, r0 + msr cpsr, r1 + + /* Set monitor vector (MVBAR) */ + ldr r0, =sm_vect_table + write_mvbar r0 + + pop {r0, pc} +END_FUNC sm_init diff --git a/core/arch/arm32/sm/sub.mk b/core/arch/arm32/sm/sub.mk new file mode 100644 index 00000000000..a4f055f2727 --- /dev/null +++ b/core/arch/arm32/sm/sub.mk @@ -0,0 +1,5 @@ +srcs-y += tee_mon.c +cflags-tee_mon.c-y += -Wno-unused-parameter + +srcs-y += sm_asm.S +srcs-y += sm.c diff --git a/core/arch/arm32/sm/tee_mon.c b/core/arch/arm32/sm/tee_mon.c new file mode 100644 index 00000000000..c67cc6d764e --- /dev/null +++ b/core/arch/arm32/sm/tee_mon.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include /* required for inits */ + +#include +#include +#include +#include +#include +#include + + + + +#ifndef WITH_UART_DRV +#include +#endif + +#define TEE_MON_MAX_NUM_ARGS 8 + +TEE_Result init_teecore(void) +{ + static int is_first = 1; + unsigned long a, s; + + /* (DEBUG) for inits at 1st TEE service: when UART is setup */ + if (!is_first) + return TEE_SUCCESS; + is_first = 0; + +#ifndef WITH_UART_DRV + /* UART tracing support */ + asc_init(); + IMSG("teecore: uart trace init"); +#endif + + /* core malloc pool init */ +#ifdef CFG_TEE_MALLOC_START + a = CFG_TEE_MALLOC_START; + s = CFG_TEE_MALLOC_SIZE; +#else + a = (unsigned long)&teecore_heap_start; + s = (unsigned long)&teecore_heap_end; + a = ((a + 1) & ~0x0FFFF) + 0x10000; /* 64kB aligned */ + s = s & ~0x0FFFF; /* 64kB aligned */ + s = s - a; +#endif + IMSG("teecore heap: paddr=0x%lX size=0x%lX (%ldkB)", a, s, s / 1024); + malloc_init((void *)a, s); + + /* init support for futur mapping of TAs */ + tee_mmu_kmap_init(); + teecore_init_ta_ram(); + teecore_init_pub_ram(); + + /* Libtomcrypt initialization */ + tee_ltc_init(); + + IMSG("teecore inits done"); + return TEE_SUCCESS; +} diff --git a/core/arch/arm32/sta/core_dirty_tests.c b/core/arch/arm32/sta/core_dirty_tests.c new file mode 100644 index 00000000000..44e4d5c6dc4 --- /dev/null +++ b/core/arch/arm32/sta/core_dirty_tests.c @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include + +#include "core_dirty_tests.h" + +/* + * Enable expect LOG macro to enable/disable dirty tests traces. + * + * #define LOG SMSG + * #define LOG(...) + */ +#define LOG(...) + +static int dirty_test_division(void); +static int dirty_test_malloc(void); + +/* exported entry points for some basic test */ +TEE_Result core_dirty_tests(uint32_t nParamTypes, + TEE_Param pParams[TEE_NUM_PARAMS]) +{ + (void)&nParamTypes; + (void)&pParams; + + if (dirty_test_division() || dirty_test_malloc()) { + EMSG("some dirty_test_xxx failed! you should enable local LOG"); + return TEE_ERROR_GENERIC; + } + return TEE_SUCCESS; +} + +/* test division support. resulting trace shall be manually checked */ +static int dirty_test_division(void) +{ + signed a, b, c, d; + bool r; + int ret = 0; + + LOG(""); + LOG("division tests (division and modulo):"); + /* get some unpredicted values to prevent compilation optimizations: */ + /* => use the stack address */ + + LOG("- test with unsigned small integers:"); + a = (signed)((unsigned)(&a) & 0xFFFFF); + b = (signed)((unsigned)(&b) & 0x00FFF) + 1; + c = a / b; + d = a % b; + r = ((b * c + d) == a); + if (!r) + ret = -1; + LOG(" 0x%08x / 0x%08x = %u / %u = %u = 0x%x)", + (unsigned)a, (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)c, + (unsigned)c); + LOG(" 0x%08x %% 0x%08x = %u %% %u = %u = 0x%x)", (unsigned)a, + (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)d, (unsigned)d); + LOG(" check results => %s", r ? "ok" : "FAILED !!!"); + LOG(""); + + LOG("- test with signed small integers, negative numerator:"); + a = (signed)(&a); + b = (signed)((unsigned)(&b) & 0x00FFF) - 1; + c = a / b; + d = a % b; + r = ((b * c + d) == a); + if (!r) + ret = -1; + LOG(" 0x%08x / 0x%08x = %d / %d = %d = 0x%x)", + (unsigned)a, (unsigned)b, (signed)a, (signed)b, (signed)c, + (unsigned)c); + LOG(" 0x%08x %% 0x%08x = %d %% %d = %d = 0x%x)", (unsigned)a, + (unsigned)b, (signed)a, (signed)b, (signed)d, (unsigned)d); + LOG(" check results => %s", r ? "ok" : "FAILED !!!"); + LOG(""); + + LOG("- test with signed small integers, negative denominator:"); + a = (signed)((unsigned)(&a) & 0xFFFFF); + b = -(signed)((unsigned)(&b) & 0x00FFF) + 1; + c = a / b; + d = a % b; + + LOG("- test with unsigned integers, big numerator (> 0x80000000):"); + a = (signed)(&a); + b = (signed)((unsigned)(&b) & 0x00FFF) + 1; + c = (signed)((unsigned)a / (unsigned)b); + d = (signed)((unsigned)a % (unsigned)b); + r = (((unsigned)b * (unsigned)c + (unsigned)d) == (unsigned)a); + if (!r) + ret = -1; + LOG(" 0x%08x / 0x%08x = %u / %u = %u = 0x%x)", + (unsigned)a, (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)c, + (unsigned)c); + LOG(" 0x%08x %% 0x%08x = %u %% %u = %u = 0x%x)", (unsigned)a, + (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)d, (unsigned)d); + LOG(" check results => %s", r ? "ok" : "FAILED !!!"); + LOG(""); + + LOG("- test with unsigned integers, big num. & denom. (> 0x80000000):"); + a = (signed)(&a); + b = (signed)((unsigned)(&a) - 1); + c = (signed)((unsigned)a / (unsigned)b); + d = (signed)((unsigned)a % (unsigned)b); + r = (((unsigned)b * (unsigned)c + (unsigned)d) == (unsigned)a); + if (!r) + ret = -1; + LOG(" 0x%08x / 0x%08x = %u / %u = %u = 0x%x)", + (unsigned)a, (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)c, + (unsigned)c); + LOG(" 0x%08x %% 0x%08x = %u %% %u = %u = 0x%x)", (unsigned)a, + (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)d, (unsigned)d); + LOG(" check results => %s", r ? "ok" : "FAILED !!!"); + LOG(""); + + return ret; +} + +/* test malloc support. resulting trace shall be manually checked */ +static int dirty_test_malloc(void) +{ + char *p1 = NULL, *p2 = NULL; + int *p3 = NULL, *p4 = NULL; + bool r; + int ret = 0; + + LOG("malloc tests (malloc, free, calloc, realloc, memalign):"); + LOG(" p1=%p p2=%p p3=%p p4=%p", p1, p2, p3, p4); + /* test malloc */ + p1 = malloc(1024); + LOG("- p1 = malloc(1024)"); + p2 = malloc(1024); + LOG("- p2 = malloc(1024)"); + LOG(" p1=%p p2=%p p3=%p p4=%p", p1, p2, p3, p4); + r = (p1 && p2); + if (!r) + ret = -1; + LOG(" => test %s", r ? "ok" : "FAILED"); + LOG(""); + + /* test realloc */ + p1 = realloc(p1, 3 * 1024); + LOG("- p1 = realloc(p1, 3*1024)"); + LOG("- free p2"); + free(p2); + p2 = malloc(1024); + LOG("- p2 = malloc(1024)"); + LOG(" p1=%p p2=%p p3=%p p4=%p", p1, p2, p3, p4); + r = (p1 && p2); + if (!r) + ret = -1; + LOG(" => test %s", r ? "ok" : "FAILED"); + LOG(""); + LOG("- free p1, p2"); + free(p1); + free(p2); + p1 = NULL; + p2 = NULL; + + /* test calloc */ + p3 = calloc(0x10, 1024); + p4 = calloc(0x100, 1024 * 1024); + LOG("- p3 = calloc(0x100, 1024)"); + LOG("- p4 = calloc(0x100, 1024*1024) too big: should fail!"); + LOG(" p1=%p p2=%p p3=%p p4=%p", p1, p2, p3, p4); + r = (p3 && !p4); + if (!r) + ret = -1; + LOG(" => test %s", r ? "ok" : "FAILED"); + LOG(""); + LOG("- free p3, p4"); + free(p3); + free(p4); + p3 = NULL; + p4 = NULL; + + /* test memalign */ + p3 = memalign(0x10000, 1024); + LOG("- p3 = memalign(%d, 1024)", 0x10000); + p1 = malloc(1024); + LOG("- p1 = malloc(1024)"); + p4 = memalign(0x10000, 1024); + LOG("- p4 = memalign(%d, 1024)", 0x10000); + LOG(" p1=%p p2=%p p3=%p p4=%p", p1, p2, p3, p4); + r = (p1 && p3 && p4); + if (!r) + ret = -1; + LOG(" => test %s", r ? "ok" : "FAILED"); + LOG(""); + LOG("- free p1, p3, p4"); + free(p1); + free(p3); + free(p4); + p1 = NULL; + p3 = NULL; + p4 = NULL; + + /* test memalign with invalid alignments */ + p3 = memalign(100, 1024); + LOG("- p3 = memalign(%d, 1024)", 100); + p4 = memalign(0, 1024); + LOG("- p4 = memalign(%d, 1024)", 0); + LOG(" p1=%p p2=%p p3=%p p4=%p", p1, p2, p3, p4); + r = (!p3 && !p4); + if (!r) + ret = -1; + LOG(" => test %s", r ? "ok" : "FAILED"); + LOG(""); + LOG("- free p3, p4"); + free(p3); + free(p4); + p3 = NULL; + p4 = NULL; + + /* test free(NULL) */ + LOG("- free NULL"); + free(NULL); + LOG(""); + LOG("malloc test done"); + + return ret; +} diff --git a/core/arch/arm32/sta/core_dirty_tests.h b/core/arch/arm32/sta/core_dirty_tests.h new file mode 100644 index 00000000000..0a9cc7b155c --- /dev/null +++ b/core/arch/arm32/sta/core_dirty_tests.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef CORE_DIRTY_TESTS_H +#define CORE_DIRTY_TESTS_H + +#include +#include + +/* basic run-time tests */ +TEE_Result core_dirty_tests(uint32_t nParamTypes, + TEE_Param pParams[TEE_NUM_PARAMS]); + +#endif /*CORE_DIRTY_TESTS_H*/ diff --git a/core/arch/arm32/sta/sta_helloworld.c b/core/arch/arm32/sta/sta_helloworld.c new file mode 100644 index 00000000000..b49ae454bfc --- /dev/null +++ b/core/arch/arm32/sta/sta_helloworld.c @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include "core_dirty_tests.h" + +#define TA_NAME "sta_helloworld.ta" + +#define STA_HELLOWORLD_UUID \ + { 0xd96a5b40, 0xc3e5, 0x21e3, \ + { 0x87, 0x94, 0x10, 0x02, 0xa5, 0xd5, 0xc6, 0x1b } } + +#define CMD_TRACE 0 +#define CMD_PARAMS 1 +#define CMD_DIRTY_TESTS 2 + +static TEE_Result test_trace(uint32_t param_types, TEE_Param params[4]) +{ + IMSG("static TA \"%s\" says \"Hello world !\"", TA_NAME); + + return TEE_SUCCESS; +} + +/* + * Supported tests on parameters + * (I, J, K, L refer to param index) + * + * Case 1: command parameters type are: 1 in/out value, 3 empty. + * => process outI.a = inI.a + inI.b + * Case 2: command parameters type are: 3 input value, 1 output value + * => process = outI.a = inJ.a + inK.a + inL.a + * Case 3: command parameters type are: 1 in/out memref, 3 empty. + * => process = outI[0] = sum(inI[0..len-1]) + */ +static TEE_Result test_entry_params(uint32_t type, TEE_Param p[4]) +{ + size_t i; + uint8_t d8, *in; + + /* case 1a: 1 input/output value argument */ + if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_INOUT) && + (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) && + (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) && + (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) { + p[0].value.a = p[0].value.a + p[0].value.b; + return TEE_SUCCESS; + } + /* case 1b: 1 input/output value argument */ + if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) && + (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_INOUT) && + (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) && + (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) { + p[1].value.a = p[1].value.a + p[1].value.b; + return TEE_SUCCESS; + } + /* case 1c: 1 input/output value argument */ + if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) && + (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) && + (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_INOUT) && + (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) { + p[2].value.a = p[2].value.a + p[2].value.b; + return TEE_SUCCESS; + } + /* case 1d: 1 input/output value argument */ + if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) && + (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) && + (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) && + (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_INOUT)) { + p[3].value.a = p[3].value.a + p[3].value.b; + return TEE_SUCCESS; + } + + /* case 2a: 3 input value arguments, 1 output value argument */ + if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_OUTPUT) && + (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_INPUT) && + (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_INPUT) && + (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_INPUT)) { + p[0].value.a = p[1].value.a + p[2].value.a + p[3].value.a; + p[0].value.b = p[1].value.b + p[2].value.b + p[3].value.b; + return TEE_SUCCESS; + } + /* case 2a: 3 input value arguments, 1 output value argument */ + if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_INPUT) && + (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_OUTPUT) && + (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_INPUT) && + (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_INPUT)) { + p[1].value.a = p[0].value.a + p[2].value.a + p[3].value.a; + p[1].value.b = p[0].value.b + p[2].value.b + p[3].value.b; + return TEE_SUCCESS; + } + /* case 2a: 3 input value arguments, 1 output value argument */ + if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_INPUT) && + (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_INPUT) && + (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_OUTPUT) && + (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_INPUT)) { + p[2].value.a = p[0].value.a + p[1].value.a + p[3].value.a; + p[2].value.b = p[0].value.b + p[1].value.b + p[3].value.b; + return TEE_SUCCESS; + } + /* case 2a: 3 input value arguments, 1 output value argument */ + if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_INPUT) && + (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_INPUT) && + (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_INPUT) && + (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_OUTPUT)) { + p[3].value.a = p[0].value.a + p[1].value.a + p[2].value.a; + p[3].value.b = p[0].value.b + p[1].value.b + p[2].value.b; + return TEE_SUCCESS; + } + + DMSG("expect memref params: 0x%X/%d - 0x%X/%d - 0x%X/%d - 0x%X/%d", + p[0].memref.buffer, p[0].memref.size, + p[1].memref.buffer, p[1].memref.size, + p[2].memref.buffer, p[2].memref.size, + p[3].memref.buffer, p[3].memref.size); + + /* case 3a: 1 in/out memref argument */ + if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_MEMREF_INOUT) && + (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) && + (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) && + (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) { + in = (uint8_t *)p[0].memref.buffer; + d8 = 0; + for (i = 0; i < p[0].memref.size; i++) + d8 += in[i]; + *(uint8_t *)p[0].memref.buffer = d8; + return TEE_SUCCESS; + } + /* case 3b: 1 in/out memref argument */ + if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) && + (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_MEMREF_INOUT) && + (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) && + (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) { + in = (uint8_t *)p[1].memref.buffer; + d8 = 0; + for (i = 0; i < p[1].memref.size; i++) + d8 += in[i]; + *(uint8_t *)p[1].memref.buffer = d8; + return TEE_SUCCESS; + } + /* case 3c: 1 in/out memref argument */ + if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) && + (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) && + (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_MEMREF_INOUT) && + (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) { + in = (uint8_t *)p[2].memref.buffer; + d8 = 0; + for (i = 0; i < p[2].memref.size; i++) + d8 += in[i]; + *(uint8_t *)p[2].memref.buffer = d8; + return TEE_SUCCESS; + } + /* case 3d: 1 in/out memref argument */ + if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) && + (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) && + (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) && + (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_MEMREF_INOUT)) { + in = (uint8_t *)p[3].memref.buffer; + d8 = 0; + for (i = 0; i < p[3].memref.size; i++) + d8 += in[i]; + *(uint8_t *)p[3].memref.buffer = d8; + return TEE_SUCCESS; + } + + EMSG("unexpected parameters"); + return TEE_ERROR_BAD_PARAMETERS; +} + +/* + * Trusted Application Entry Points + */ + +static TEE_Result create_ta(void) +{ + DMSG("create entry point for static ta \"%s\"", TA_NAME); + return TEE_SUCCESS; +} + +static void destroy_ta(void) +{ + DMSG("destroy entry point for static ta \"%s\"", TA_NAME); +} + +static TEE_Result open_session(uint32_t nParamTypes, TEE_Param pParams[4], + void **ppSessionContext) +{ + DMSG("open entry point for static ta \"%s\"", TA_NAME); + return TEE_SUCCESS; +} + +static void close_session(void *pSessionContext) +{ + DMSG("close entry point for static ta \"%s\"", TA_NAME); +} + +static TEE_Result invoke_command(void *pSessionContext, uint32_t nCommandID, + uint32_t nParamTypes, TEE_Param pParams[4]) +{ + DMSG("command entry point for static ta \"%s\"", TA_NAME); + + switch (nCommandID) { + case CMD_TRACE: + return test_trace(nParamTypes, pParams); + case CMD_PARAMS: + return test_entry_params(nParamTypes, pParams); + case CMD_DIRTY_TESTS: + return core_dirty_tests(nParamTypes, pParams); + default: + break; + } + return TEE_ERROR_BAD_PARAMETERS; +} + +__attribute__ ((section("ta_head_section"))) + const ta_static_head_t sta_helloworld_head = { + + .uuid = STA_HELLOWORLD_UUID, + .name = (char *)TA_NAME, + .create_entry_point = create_ta, + .destroy_entry_point = destroy_ta, + .open_session_entry_point = open_session, + .close_session_entry_point = close_session, + .invoke_command_entry_point = invoke_command, + +}; diff --git a/core/arch/arm32/sta/sub.mk b/core/arch/arm32/sta/sub.mk new file mode 100644 index 00000000000..a1a2c4b2890 --- /dev/null +++ b/core/arch/arm32/sta/sub.mk @@ -0,0 +1,6 @@ +srcs-y += sta_helloworld.c +cflags-sta_helloworld.c-y += -Wno-unused-parameter + +srcs-y += core_dirty_tests.c +cflags-core_dirty_tests.c-y += -Wno-format +cflags-core_dirty_tests.c-y += -Wno-format-nonliteral -Wno-format-security diff --git a/core/arch/arm32/tee/entry.c b/core/arch/arm32/tee/entry.c new file mode 100644 index 00000000000..710ee134f0f --- /dev/null +++ b/core/arch/arm32/tee/entry.c @@ -0,0 +1,448 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define SHM_CACHE_ATTRS \ + (core_mmu_is_shm_cached() ? \ + (TEESMC_ATTR_CACHE_DEFAULT << TEESMC_ATTR_CACHE_SHIFT) : 0 ) + +static bool copy_in_params(const struct teesmc32_param *params, + uint32_t num_params, uint32_t *param_types, + uint32_t param_attr[TEE_NUM_PARAMS], + TEE_Param tee_params[TEE_NUM_PARAMS]) +{ + size_t n; + uint8_t pt[4]; + + *param_types = 0; + + if (num_params > TEE_NUM_PARAMS) + return false; + + for (n = 0; n < num_params; n++) { + if (params[n].attr & TEESMC_ATTR_META) + return false; + + pt[n] = params[n].attr & TEESMC_ATTR_TYPE_MASK; + + param_attr[n] = (params[n].attr >> TEESMC_ATTR_CACHE_SHIFT) & + TEESMC_ATTR_CACHE_MASK; + + if ((params[n].attr & TEESMC_ATTR_TYPE_MASK) == + TEESMC_ATTR_TYPE_NONE) { + tee_params[n].value.a = 0; + tee_params[n].value.b = 0; + } else { + tee_params[n].value.a = params[n].u.value.a; + tee_params[n].value.b = params[n].u.value.b; + } + } + for (; n < TEE_NUM_PARAMS; n++) { + pt[n] = TEE_PARAM_TYPE_NONE; + param_attr[n] = 0; + tee_params[n].value.a = 0; + tee_params[n].value.b = 0; + } + + *param_types = TEE_PARAM_TYPES(pt[0], pt[1], pt[2], pt[3]); + + return true; +} + +static void copy_out_param(const TEE_Param tee_params[TEE_NUM_PARAMS], + uint32_t param_types, uint32_t num_params, + struct teesmc32_param *params) +{ + size_t n; + + for (n = 0; n < num_params; n++) { + switch (TEE_PARAM_TYPE_GET(param_types, n)) { + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + params[n].u.memref.size = tee_params[n].memref.size; + break; + case TEE_PARAM_TYPE_VALUE_OUTPUT: + case TEE_PARAM_TYPE_VALUE_INOUT: + params[n].u.value.a = tee_params[n].value.a; + params[n].u.value.b = tee_params[n].value.b; + break; + default: + break; + } + } +} + +/* + * Extracts mandatory parameter for open session. + * + * Returns + * false : mandatory parameter wasn't found or malformatted + * true : paramater found and OK + */ +static bool get_open_session_meta(struct teesmc32_arg *arg32, + uint32_t num_params, size_t *num_meta, + struct teesmc_meta_open_session **meta) +{ + struct teesmc32_param *params = TEESMC32_GET_PARAMS(arg32); + uint32_t phmeta; + const uint8_t req_attr = TEESMC_ATTR_META | + TEESMC_ATTR_TYPE_MEMREF_INPUT | + SHM_CACHE_ATTRS; + + if (num_params < (*num_meta + 1)) + return false; + + if (params[*num_meta].attr != req_attr) + return false; + + if (params[*num_meta].u.memref.size != + sizeof(struct teesmc_meta_open_session)) + return false; + + phmeta = params[*num_meta].u.memref.buf_ptr; + if (!tee_pbuf_is_non_sec(phmeta, + sizeof(struct teesmc_meta_open_session))) + return false; + + if (core_pa2va(phmeta, (void *)meta)) + return false; + + (*num_meta)++; + return true; +} + +/* + * Extracts optional pointer to a Trusted Application. + * + * Returns + * false : malformatted TA parameter + * true : if TA parameter wasn't found or if it was found and OK + */ +static bool get_open_session_ta(struct teesmc32_arg *arg32, size_t num_params, + size_t *num_meta, kta_signed_header_t **ta) +{ + struct teesmc32_param *params = TEESMC32_GET_PARAMS(arg32); + uint32_t ph; + size_t len; + const uint8_t req_attr = TEESMC_ATTR_META | + TEESMC_ATTR_TYPE_MEMREF_INPUT | + SHM_CACHE_ATTRS; + + if (num_params < (*num_meta + 1)) + return false; + + if (!(params[*num_meta].attr & TEESMC_ATTR_META)) + return true; + + if (params[*num_meta].attr != req_attr) + return false; + + ph = params[*num_meta].u.memref.buf_ptr; + if (params[*num_meta].u.memref.size < sizeof(kta_signed_header_t)) + return false; + + if (!tee_pbuf_is_non_sec(ph, sizeof(kta_signed_header_t))) + return false; + + if (core_pa2va(ph, (void *)ta)) + return false; + + len = (*ta)->size_of_signed_header + (*ta)->size_of_payload; + if (params[*num_meta].u.memref.size < len) + return false; + + if (!tee_pbuf_is_non_sec(ph, len)) + return false; + + (*num_meta)++; + return true; +} + +static void entry_open_session(struct thread_smc_args *args, + struct teesmc32_arg *arg32, uint32_t num_params) +{ + struct tee_dispatch_open_session_in in; + struct tee_dispatch_open_session_out out; + struct teesmc_meta_open_session *meta; + struct teesmc32_param *params = TEESMC32_GET_PARAMS(arg32); + size_t num_meta = 0; + + if (!get_open_session_meta(arg32, num_params, &num_meta, &meta)) + goto bad_params; + + in.ta = NULL; + if (!get_open_session_ta(arg32, num_params, &num_meta, &in.ta)) + goto bad_params; + + TEE_COMPILE_TIME_ASSERT(sizeof(TEE_UUID) == TEESMC_UUID_LEN); + memcpy(&in.uuid, &meta->uuid, sizeof(TEE_UUID)); + memcpy(&in.clnt_id.uuid, &meta->clnt_uuid, sizeof(TEE_UUID)); + in.clnt_id.login = meta->clnt_login; + + if (!copy_in_params(params + num_meta, num_params - num_meta, + &in.param_types, in.param_attr, in.params)) + goto bad_params; + + (void)tee_dispatch_open_session(&in, &out); + if (out.msg.res == TEE_STE_ERROR_SYSTEM_BUSY) { + args->a0 = TEESMC_RETURN_EBUSY; + return; + } + + copy_out_param(out.params, in.param_types, num_params - num_meta, + params + num_meta); + + arg32->session = (uint32_t)out.sess; + arg32->ret = out.msg.res; + arg32->ret_origin = out.msg.err; + args->a0 = TEESMC_RETURN_OK; + return; + +bad_params: + DMSG("Bad params"); + arg32->ret = TEE_ERROR_BAD_PARAMETERS; + arg32->ret_origin = TEE_ORIGIN_TEE; + args->a0 = TEESMC_RETURN_OK; +} + +static void entry_close_session(struct thread_smc_args *args, + struct teesmc32_arg *arg32, uint32_t num_params) +{ + + if (num_params == 0) { + struct tee_close_session_in in; + uint32_t ret; + + in.sess = arg32->session; + ret = tee_dispatch_close_session(&in); + if (ret == TEE_STE_ERROR_SYSTEM_BUSY) { + args->a0 = TEESMC_RETURN_EBUSY; + return; + } + arg32->ret = ret; + } else { + arg32->ret = TEE_ERROR_BAD_PARAMETERS; + } + + arg32->ret_origin = TEE_ORIGIN_TEE; + args->a0 = TEESMC_RETURN_OK; +} + +static void entry_invoke_command(struct thread_smc_args *args, + struct teesmc32_arg *arg32, uint32_t num_params) +{ + struct tee_dispatch_invoke_command_in in; + struct tee_dispatch_invoke_command_out out; + struct teesmc32_param *params = TEESMC32_GET_PARAMS(arg32); + + if (!copy_in_params(params, num_params, + &in.param_types, in.param_attr, in.params)) { + arg32->ret = TEE_ERROR_BAD_PARAMETERS; + arg32->ret_origin = TEE_ORIGIN_TEE; + args->a0 = TEESMC_RETURN_OK; + return; + } + + in.sess = (TEE_Session *)arg32->session; + in.cmd = arg32->ta_func; + (void)tee_dispatch_invoke_command(&in, &out); + if (out.msg.res == TEE_STE_ERROR_SYSTEM_BUSY) { + args->a0 = TEESMC_RETURN_EBUSY; + return; + } + + copy_out_param(out.params, in.param_types, num_params, params); + + arg32->ret = out.msg.res; + arg32->ret_origin = out.msg.err; + args->a0 = TEESMC_RETURN_OK; +} + +static void entry_cancel(struct thread_smc_args *args, + struct teesmc32_arg *arg32, uint32_t num_params) +{ + + if (num_params == 0) { + struct tee_dispatch_cancel_command_in in; + struct tee_dispatch_cancel_command_out out; + + in.sess = (TEE_Session *)arg32->session; + (void)tee_dispatch_cancel_command(&in, &out); + + if (out.msg.res == TEE_STE_ERROR_SYSTEM_BUSY) { + args->a0 = TEESMC_RETURN_EBUSY; + return; + } + + arg32->ret = out.msg.res; + arg32->ret_origin = out.msg.err; + } else { + arg32->ret = TEE_ERROR_BAD_PARAMETERS; + arg32->ret_origin = TEE_ORIGIN_TEE; + } + + args->a0 = TEESMC_RETURN_OK; +} + + + +static void tee_entry_call_with_arg(struct thread_smc_args *args) +{ + struct teesmc32_arg *arg32; + uint32_t num_params; + + if (args->a0 != TEESMC32_CALL_WITH_ARG && + args->a0 != TEESMC32_FASTCALL_WITH_ARG) { + EMSG("Unknown SMC 0x%x\n", args->a0); + DMSG("Expected 0x%x or 0x%x\n", + TEESMC32_CALL_WITH_ARG, TEESMC32_FASTCALL_WITH_ARG); + args->a0 = TEESMC_RETURN_UNKNOWN_FUNCTION; + return; + } + + if (args->a0 == TEESMC32_CALL_WITH_ARG) + thread_set_irq(true); /* Enable IRQ for STD calls */ + + if (!tee_pbuf_is_non_sec(args->a1, sizeof(struct teesmc32_arg)) || + !TEE_ALIGNMENT_IS_OK(args->a1, struct teesmc32_arg) || + core_pa2va(args->a1, (void *)&arg32)) { + EMSG("Bad arg address 0x%x\n", args->a1); + args->a0 = TEESMC_RETURN_EBADADDR; + return; + } + + num_params = arg32->num_params; + if (!tee_pbuf_is_non_sec(args->a1, TEESMC32_GET_ARG_SIZE(num_params))) { + EMSG("Bad arg address 0x%x\n", args->a1); + args->a0 = TEESMC_RETURN_EBADADDR; + return; + } + + if (args->a0 == TEESMC32_CALL_WITH_ARG) { + switch (arg32->cmd) { + case TEESMC_CMD_OPEN_SESSION: + entry_open_session(args, arg32, num_params); + break; + case TEESMC_CMD_CLOSE_SESSION: + entry_close_session(args, arg32, num_params); + break; + case TEESMC_CMD_INVOKE_COMMAND: + entry_invoke_command(args, arg32, num_params); + break; + case TEESMC_CMD_CANCEL: + entry_cancel(args, arg32, num_params); + break; + default: + EMSG("Unknown cmd 0x%x\n", arg32->cmd); + args->a0 = TEESMC_RETURN_EBADCMD; + } + } else { + EMSG("Unknown fastcall cmd 0x%x\n", arg32->cmd); + args->a0 = TEESMC_RETURN_EBADCMD; + } +} + +void tee_entry(struct thread_smc_args *args) +{ + switch (args->a0) { + case TEESMC32_CALLS_COUNT: + tee_entry_get_api_call_count(args); + break; + case TEESMC32_CALLS_UID: + tee_entry_get_api_uuid(args); + break; + case TEESMC32_CALLS_REVISION: + tee_entry_get_api_revision(args); + break; + case TEESMC32_CALL_GET_OS_UUID: + tee_entry_get_os_uuid(args); + break; + case TEESMC32_CALL_GET_OS_REVISION: + tee_entry_get_os_revision(args); + break; + case TEESMC32_CALL_WITH_ARG: + case TEESMC64_CALL_WITH_ARG: + tee_entry_call_with_arg(args); + break; + default: + args->a0 = TEESMC_RETURN_UNKNOWN_FUNCTION; + break; + } +} + +size_t tee_entry_generic_get_api_call_count(void) +{ + /* + * All the differnt calls handled in this file. If the specific + * target has additional calls it will call this function and + * add the number of calls the target has added. + */ + return 7; +} + +void __attribute__((weak)) tee_entry_get_api_call_count( + struct thread_smc_args *args) +{ + args->a0 = tee_entry_generic_get_api_call_count(); +} + +void __attribute__((weak)) tee_entry_get_api_uuid(struct thread_smc_args *args) +{ + args->a0 = TEESMC_UID_R0; + args->a1 = TEESMC_UID_R1; + args->a2 = TEESMC_UID_R2; + args->a3 = TEESMC_UID32_R3; +} + +void __attribute__((weak)) tee_entry_get_api_revision( + struct thread_smc_args *args) +{ + args->a0 = TEESMC_REVISION_MAJOR; + args->a1 = TEESMC_REVISION_MINOR; +} + +void __attribute__((weak)) tee_entry_get_os_uuid(struct thread_smc_args *args) +{ + /* Not implemented */ + args->a0 = TEESMC_RETURN_UNKNOWN_FUNCTION; +} + +void __attribute__((weak)) tee_entry_get_os_revision( + struct thread_smc_args *args) +{ + /* Not implemented */ + args->a0 = TEESMC_RETURN_UNKNOWN_FUNCTION; +} diff --git a/core/arch/arm32/tee/sub.mk b/core/arch/arm32/tee/sub.mk new file mode 100644 index 00000000000..9b9b940c908 --- /dev/null +++ b/core/arch/arm32/tee/sub.mk @@ -0,0 +1,2 @@ +srcs-y += tee_svc_asm.S +srcs-y += entry.c diff --git a/core/arch/arm32/tee/tee_svc_asm.S b/core/arch/arm32/tee/tee_svc_asm.S new file mode 100644 index 00000000000..a4156d496b4 --- /dev/null +++ b/core/arch/arm32/tee/tee_svc_asm.S @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "tee_syscall_numbers.h" + +.global tee_svc_enter_user_mode +.global tee_svc_sys_return +.global tee_svc_syscall + +.set SPSR_T_BIT, (1 << 5) +.set SPSR_IT_MASK, 0x0600FC00 +.set SPSR_IT_MASK1, 0x06000000 +.set SPSR_IT_MASK2, 0x0000FC00 + +.section .text +.balign 4 +.code 32 + +/* + * Function called from the vector table when a svc exception is received. + * This function handles entry and exit from a system call. + */ +.func tee_svc_syscall +tee_svc_syscall: + push {r4 - r12, lr} + mov r8, sp + + /* Restore IRQ which are disabled on exception entry */ + push {r0-r3} + blx thread_restore_irq + pop {r0-r3} + + /* + * Copy eventual arguments passed on the user stack. + * + * r5 holds the address of the first word + * r6 holds the number of words + * + * TODO figure out how to avoid stack overflow because of too much data + * passed on the stack. + */ + sub sp, sp, r6, lsl #2 + cmp r6, #0 + beq .Lno_args + push {r0} + push {r1-r3} + mov r0, #0 + mov r2, r5 + add r1, sp, #(4 * 4) + mov r3, r6, lsl #2 + ldr lr, =tee_svc_copy_from_user + blx lr + + /* If copy failed return the error */ + cmp r0, #0 + pop {r1-r3} + addne sp, sp, #4 + popeq {r0} + bne .Lret +.Lno_args: + + /* + * Find the system call and call the function. + * + * System call number is passed in r7. + */ + ldr r12, =tee_svc_syscall_table + cmp r7, #TEE_SCN_MAX + /* Either syscall function should return to cleanup (.Lret) */ + ldr lr, =.Lret + ldrls pc, [r12, r7, lsl #2] /* if valid syscall number */ + ldr pc, =tee_svc_sys_nocall /* if invalid syscall number */ +.Lret: + mov sp, r8 + pop {r4 - r12, lr} + movs pc, lr +.endfunc + + + +@ TEE_Result tee_svc_enter_user_mode( +@ uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, +@ tee_uaddr_t sp, tee_uaddr_t user_func, +@ uint32_t *panicked, uint32_t *panic_code); +.func tee_svc_enter_user_mode +tee_svc_enter_user_mode: + /* + * Save all registers to allow tee_svc_sys_return() to + * resume execution as if this function would have returned. + * This is also used in tee_svc_sys_panic(). + * + * If stack usage of this function is changed tee_svc_sys_return() + * and tee_svc_sys_panic() has to be updated. + */ + push {r4-r12,lr} + + ldr r4, [sp, #(10 * 0x4)] /* user stack pointer */ + ldr r5, [sp, #(11 * 0x4)] /* user function */ + + /* Save user sp */ + stmfd sp, {sp}^ /* store r13 user mode */ + nop + sub sp, sp, #4 /* update stack pointer */ + + /* Switch from Supervisor mode to System mode */ + mrs r6, cpsr + mrs r7, cpsr + orr r6, #0xF + msr cpsr, r6 + + /* Setup user stack */ + mov sp, r4 + + /* Switch back to Supervisor mode to have a spsr to modify */ + msr cpsr, r7 + + /* + * Set the saved Processors Status Register to user mode to allow entry + * of user mode through movs below. Also update thumbstate since movs + * doesn't do that automatically. + */ + bic r6, #0xF + tst r5, #1 /* If it's odd we should switch to thumb mode */ + orrne r6, #SPSR_T_BIT /* Enable thumb mode */ + biceq r6, #SPSR_T_BIT /* Disable thumb mode */ + bicne r6, #SPSR_IT_MASK1 /* Clear IT state for thumb mode */ + bicne r6, #SPSR_IT_MASK2 /* Clear IT state for thumb mode */ + msr spsr_cxsf, r6 + + /* + * Don't allow return from this function, return is done through + * tee_svc_sys_return() below. + */ + mov lr, #0 + /* Call the user function with its arguments */ + movs pc, r5 +.endfunc + +@ tee_svc_sys_return(uint32_t ret, uint32_t param_types, void *params); +.func tee_svc_sys_return +tee_svc_sys_return: + mov sp, r8 /* Restore sp in case extra parameters was passed */ + pop {r4-r12,lr} /* Match the push in tee_svc_syscall() */ + + /* Restore user sp */ + ldmfd sp, {sp}^ /* store r13 user mode */ + nop + add sp, sp, #4 /* update stack pointer */ + + pop {r4-r12,pc} /* Match the push in tee_svc_enter_user_mode() */ +.endfunc + +@ void tee_svc_sys_panic(uint32_t code); +.func tee_svc_sys_panic +tee_svc_sys_panic: + mov sp, r8 /* Restore sp in case extra parameters was passed */ + pop {r4-r12,lr} /* Match the push in tee_svc_syscall() */ + +.global tee_svc_user_ta_panic_from_pager +tee_svc_user_ta_panic_from_pager: + ldr r1, [sp, #(13 * 0x4)] /* &session->panicked */ + mov r2, #1 /* true */ + str r2, [r1] /* update session->panicked */ + + ldr r1, [sp, #(14 * 0x4)] /* &session->panic_code */ + str r0, [r1] /* update session->panic_code */ + + /* Restore user sp */ + ldmfd sp, {sp}^ /* store r13 user mode */ + nop + add sp, sp, #4 /* update stack pointer */ + + pop {r4-r12,pc} /* Match the push in tee_svc_enter_user_mode() */ +.endfunc + + + .section .rodata +tee_svc_syscall_table: +.word tee_svc_sys_return +.word tee_svc_sys_log +.word tee_svc_sys_panic +.word tee_svc_sys_dummy +.word tee_svc_sys_dummy_7args +.word tee_svc_sys_get_property +.word tee_svc_open_ta_session +.word tee_svc_close_ta_session +.word tee_svc_invoke_ta_command +.word tee_svc_check_access_rights +.word tee_svc_get_cancellation_flag +.word tee_svc_unmask_cancellation +.word tee_svc_mask_cancellation +.word tee_svc_wait +.word tee_svc_get_time +.word tee_svc_set_ta_time +.word tee_svc_cryp_state_alloc +.word tee_svc_cryp_state_copy +.word tee_svc_cryp_state_free +.word tee_svc_hash_init +.word tee_svc_hash_update +.word tee_svc_hash_final +.word tee_svc_cipher_init +.word tee_svc_cipher_update +.word tee_svc_cipher_final +.word tee_svc_cryp_obj_get_info +.word tee_svc_cryp_obj_restrict_usage +.word tee_svc_cryp_obj_get_attr +.word tee_svc_cryp_obj_alloc +.word tee_svc_cryp_obj_close +.word tee_svc_cryp_obj_reset +.word tee_svc_cryp_obj_populate +.word tee_svc_cryp_obj_copy +.word tee_svc_cryp_derive_key +.word tee_svc_cryp_random_number_generate +.word tee_svc_authenc_init +.word tee_svc_authenc_update_aad +.word tee_svc_authenc_update_payload +.word tee_svc_authenc_enc_final +.word tee_svc_authenc_dec_final +.word tee_svc_asymm_operate +.word tee_svc_asymm_verify +.word tee_svc_storage_obj_open +.word tee_svc_storage_obj_create +.word tee_svc_storage_obj_del +.word tee_svc_storage_obj_rename +.word tee_svc_storage_alloc_enum +.word tee_svc_storage_free_enum +.word tee_svc_storage_reset_enum +.word tee_svc_storage_start_enum +.word tee_svc_storage_next_enum +.word tee_svc_storage_obj_read +.word tee_svc_storage_obj_write +.word tee_svc_storage_obj_trunc +.word tee_svc_storage_obj_seek +.word tee_svc_obj_generate_key diff --git a/core/core.mk b/core/core.mk new file mode 100644 index 00000000000..40ed5721a26 --- /dev/null +++ b/core/core.mk @@ -0,0 +1,51 @@ +include mk/cleanvars.mk + +# Set current submodule (used for module specific flags compile result etc) +sm := core +sm-$(sm) := y + +arch-dir := core/arch/$(ARCH) +platform-dir := $(arch-dir)/plat-$(PLATFORM) +include $(platform-dir)/conf.mk + +cppflags$(sm) += -Icore/include $(platform-cppflags) $(core-platform-cppflags) +cflags$(sm) += $(platform-cflags) $(core-platform-cflags) +aflags$(sm) += $(platform-aflags) $(core-platform-aflags) + +# Config flags from mk/config.mk +cppflags$(sm) += -DCFG_TEE_TA_LOG_LEVEL=$(CFG_TEE_TA_LOG_LEVEL) +cppflags$(sm) += -DCFG_TEE_FW_DEBUG=$(CFG_TEE_FW_DEBUG) +cppflags$(sm) += -DCFG_TEE_CORE_LOG_LEVEL=$(CFG_TEE_CORE_LOG_LEVEL) +cppflags$(sm) += -DCFG_TEE_CORE_DYNAMIC_SUPPORT=$(CFG_TEE_CORE_DYNAMIC_SUPPORT) + +cppflags$(sm) += -Ilib/libutee/include + +# +# Do libraries +# + +# Set a prefix to avoid conflicts with user TAs that will use the same +# source but with different flags below +base-prefix := $(sm)- +libname = utils +libdir = lib/libutils +include mk/lib.mk + +libname = mpa +libdir = lib/libmpa +include mk/lib.mk +base-prefix := + +libname = tomcrypt +libdir = core/lib/libtomcrypt +include mk/lib.mk + +# +# Do main source +# +subdirs = $(core-platform-subdirs) core +include mk/subdir.mk +include mk/compile.mk +include $(platform-dir)/link.mk + + diff --git a/core/default_signing.properties b/core/default_signing.properties new file mode 100644 index 00000000000..fd6c7dbfeb6 --- /dev/null +++ b/core/default_signing.properties @@ -0,0 +1,11 @@ +PAYLOAD_HASH_TYPE=SHA256_HASH +LOAD_ADDRESS=0x0 +START_ADDRESS=0x0 +DMA_FLAG=false +PKA_FLAG=false +BUFFER_SIZE=8k +SW_VERSION=0 +MAJOR_BUILD_VERSION=0 +MINOR_BUILD_VERSION=0 +FLAGS=0 +TRUSTED_APP_HASH_TYPE=SHA256_HASH diff --git a/core/drivers/gic.c b/core/drivers/gic.c new file mode 100644 index 00000000000..918297ff381 --- /dev/null +++ b/core/drivers/gic.c @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include + +/* Offsets from gic.gicc_base */ +#define GICC_CTLR (0x000) +#define GICC_IAR (0x00C) +#define GICC_EOIR (0x010) + +#define GICC_CTLR_ENABLEGRP0 (1 << 0) +#define GICC_CTLR_ENABLEGRP1 (1 << 1) +#define GICC_CTLR_FIQEN (1 << 3) + +/* Offsets from gic.gicd_base */ +#define GICD_CTLR (0x000) +#define GICD_TYPER (0x004) +#define GICD_IGROUPR(n) (0x080 + (n) * 4) +#define GICD_ISENABLER(n) (0x100 + (n) * 4) +#define GICD_ICENABLER(n) (0x180 + (n) * 4) +#define GICD_ICPENDR(n) (0x280 + (n) * 4) +#define GICD_IPRIORITYR(n) (0x400 + (n) * 4) +#define GICD_ITARGETSR(n) (0x800 + (n) * 4) + +#define GICD_CTLR_ENABLEGRP0 (1 << 0) +#define GICD_CTLR_ENABLEGRP1 (1 << 1) + +/* Maximum number of interrups a GIC can support */ +#define GIC_MAX_INTS 1020 + + +static struct { + vaddr_t gicc_base; + vaddr_t gicd_base; + size_t max_it; +} gic; + +static size_t probe_max_it(void) +{ + int i; + uint32_t old_ctlr; + size_t ret = 0; + + /* + * Probe which interrupt number is the largest. + */ + old_ctlr = read32(gic.gicc_base + GICC_CTLR); + write32(0, gic.gicc_base + GICC_CTLR); + for (i = GIC_MAX_INTS / 32; i > 0; i--) { + uint32_t old_reg; + uint32_t reg; + int b; + + old_reg = read32(gic.gicd_base + GICD_ISENABLER(i)); + write32(0xffffffff, gic.gicd_base + GICD_ISENABLER(i)); + reg = read32(gic.gicd_base + GICD_ISENABLER(i)); + write32(old_reg, gic.gicd_base + GICD_ICENABLER(i)); + for (b = 31; b > 0; b--) { + if ((1 << b) & reg) { + ret = i * 32 + b; + goto out; + } + } + } +out: + write32(old_ctlr, gic.gicc_base + GICC_CTLR); + return ret; +} + +void gic_init(vaddr_t gicc_base, vaddr_t gicd_base) +{ + size_t n; + + gic.gicc_base = gicc_base; + gic.gicd_base = gicd_base; + gic.max_it = probe_max_it(); + + for (n = 0; n <= gic.max_it / 32; n++) { + /* Disable interrupts */ + write32(0xffffffff, gic.gicd_base + GICD_ICENABLER(n)); + + /* Make interrupts non-pending */ + write32(0xffffffff, gic.gicd_base + GICD_ICPENDR(n)); + + /* Mark interrupts non-secure */ + write32(0xffffffff, gic.gicd_base + GICD_IGROUPR(n)); + } + + /* Enable GIC */ + write32(GICC_CTLR_ENABLEGRP0 | GICC_CTLR_ENABLEGRP1 | GICC_CTLR_FIQEN, + gic.gicc_base + GICC_CTLR); + write32(GICD_CTLR_ENABLEGRP0 | GICD_CTLR_ENABLEGRP1, + gic.gicd_base + GICD_CTLR); +} + +void gic_it_add(size_t it) +{ + size_t idx = it / 32; + uint32_t mask = 1 << (it % 32); + + assert(it <= gic.max_it); /* Not too large */ + + /* Disable the interrupt */ + write32(mask, gic.gicd_base + GICD_ICENABLER(idx)); + /* Make it non-pending */ + write32(mask, gic.gicd_base + GICD_ICPENDR(idx)); + /* Assign it to group0 */ + write32(read32(gic.gicd_base + GICD_IGROUPR(idx)) & ~mask, + gic.gicd_base + GICD_IGROUPR(idx)); +} + +void gic_it_set_cpu_mask(size_t it, uint8_t cpu_mask) +{ + size_t idx = it / 32; + uint32_t mask = 1 << (it % 32); + uint32_t target; + + assert(it <= gic.max_it); /* Not too large */ + /* Assigned to group0 */ + assert(!(read32(gic.gicd_base + GICD_IGROUPR(idx)) & mask)); + + /* Route it to selected CPUs */ + target = read32(gic.gicd_base + GICD_ITARGETSR(it / 4)); + target &= ~(0xff << ((it % 4) * 8)); + target |= cpu_mask << ((it % 4) * 8); + DMSG("cpu_mask: writing 0x%x to 0x%x\n", + target, gic.gicd_base + GICD_ITARGETSR(it / 4)); + write32(target, gic.gicd_base + GICD_ITARGETSR(it / 4)); + DMSG("cpu_mask: 0x%x\n", + read32(gic.gicd_base + GICD_ITARGETSR(it / 4))); +} + +void gic_it_set_prio(size_t it, uint8_t prio) +{ + size_t idx = it / 32; + uint32_t mask = 1 << (it % 32); + + assert(it <= gic.max_it); /* Not too large */ + /* Assigned to group0 */ + assert(!(read32(gic.gicd_base + GICD_IGROUPR(idx)) & mask)); + + /* Set prio it to selected CPUs */ + DMSG("prio: writing 0x%x to 0x%x\n", + prio, gic.gicd_base + GICD_IPRIORITYR(0) + it); + write8(prio, gic.gicd_base + GICD_IPRIORITYR(0) + it); +} + +void gic_it_enable(size_t it) +{ + size_t idx = it / 32; + uint32_t mask = 1 << (it % 32); + + assert(it <= gic.max_it); /* Not too large */ + /* Assigned to group0 */ + assert(!(read32(gic.gicd_base + GICD_IGROUPR(idx)) & mask)); + /* Not enabled yet */ + assert(!(read32(gic.gicd_base + GICD_ISENABLER(idx)) & mask)); + + /* Enable the interrupt */ + write32(mask, gic.gicd_base + GICD_ISENABLER(idx)); +} + +void gic_it_disable(size_t it) +{ + size_t idx = it / 32; + uint32_t mask = 1 << (it % 32); + + assert(it <= gic.max_it); /* Not too large */ + /* Assigned to group0 */ + assert(!(read32(gic.gicd_base + GICD_IGROUPR(idx)) & mask)); + + /* Disable the interrupt */ + write32(mask, gic.gicd_base + GICD_ICENABLER(idx)); +} + +uint32_t gic_read_iar(void) +{ + return read32(gic.gicc_base + GICC_IAR); +} + +void gic_write_eoir(uint32_t eoir) +{ + write32(eoir, gic.gicc_base + GICC_EOIR); +} + diff --git a/core/drivers/sub.mk b/core/drivers/sub.mk new file mode 100644 index 00000000000..4562e6da2a0 --- /dev/null +++ b/core/drivers/sub.mk @@ -0,0 +1,2 @@ +srcs-y += uart.c +srcs-y += gic.c diff --git a/core/drivers/uart.c b/core/drivers/uart.c new file mode 100644 index 00000000000..f4448c6440e --- /dev/null +++ b/core/drivers/uart.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2014, Linaro Limited + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include + +#define UART_DR 0x00 /* data register */ +#define UART_RSR_ECR 0x04 /* receive status or error clear */ +#define UART_DMAWM 0x08 /* DMA watermark configure */ +#define UART_TIMEOUT 0x0C /* Timeout period */ +/* reserved space */ +#define UART_FR 0x18 /* flag register */ +#define UART_LCRH_RX 0x1C /*receive line control */ +#define UART_ILPR 0x20 /* IrDA low-poer */ +#define UART_IBRD 0x24 /* integer baud register */ +#define UART_FBRD 0x28 /* fractional baud register */ +#define UART_LCRH_TX 0x2C /* transmit line control */ +#define UART_CR 0x30 /* control register */ +#define UART_IFLS 0x34 /* interrupt FIFO level select */ +#define UART_IMSC 0x38 /* interrupt mask set/clear */ +#define UART_RIS 0x3C /* raw interrupt register */ +#define UART_MIS 0x40 /* masked interrupt register */ +#define UART_ICR 0x44 /* interrupt clear register */ +#define UART_DMACR 0x48 /* DMA control register */ + +/* flag register bits */ +#define UART_FR_RTXDIS (1 << 13) +#define UART_FR_TERI (1 << 12) +#define UART_FR_DDCD (1 << 11) +#define UART_FR_DDSR (1 << 10) +#define UART_FR_DCTS (1 << 9) +#define UART_FR_RI (1 << 8) +#define UART_FR_TXFE (1 << 7) +#define UART_FR_RXFF (1 << 6) +#define UART_FR_TXFF (1 << 5) +#define UART_FR_RXFE (1 << 4) +#define UART_FR_BUSY (1 << 3) +#define UART_FR_DCD (1 << 2) +#define UART_FR_DSR (1 << 1) +#define UART_FR_CTS (1 << 0) + +/* transmit/recieve line register bits */ +#define UART_LCRH_SPS (1 << 7) +#define UART_LCRH_WLEN_8 (3 << 5) +#define UART_LCRH_WLEN_7 (2 << 5) +#define UART_LCRH_WLEN_6 (1 << 5) +#define UART_LCRH_WLEN_5 (0 << 5) +#define UART_LCRH_FEN (1 << 4) +#define UART_LCRH_STP2 (1 << 3) +#define UART_LCRH_EPS (1 << 2) +#define UART_LCRH_PEN (1 << 1) +#define UART_LCRH_BRK (1 << 0) + +/* control register bits */ +#define UART_CR_CTSEN (1 << 15) +#define UART_CR_RTSEN (1 << 14) +#define UART_CR_OUT2 (1 << 13) +#define UART_CR_OUT1 (1 << 12) +#define UART_CR_RTS (1 << 11) +#define UART_CR_DTR (1 << 10) +#define UART_CR_RXE (1 << 9) +#define UART_CR_TXE (1 << 8) +#define UART_CR_LPE (1 << 7) +#define UART_CR_OVSFACT (1 << 3) +#define UART_CR_UARTEN (1 << 0) + +#define UART_IMSC_RXIM (1 << 4) + +void uart_flush_tx_fifo(vaddr_t base) +{ + while (!(read32(base + UART_FR) & UART_FR_TXFE)) + ; +} + +void uart_init(vaddr_t base) +{ + write32(0, base + UART_RSR_ECR); + + /* Configure TX to 8 bits, 1 stop bit, no parity, fifo enabled. */ + write32(UART_LCRH_WLEN_8 | UART_LCRH_FEN, base + UART_LCRH_TX); + + write32(UART_IMSC_RXIM, base + UART_IMSC); + + /* Enable UART and TX */ + write32(UART_CR_UARTEN | UART_CR_TXE | UART_CR_RXE, base + UART_CR); + + uart_flush_tx_fifo(base); +} + +void uart_putc(int ch, vaddr_t base) +{ + /* + * Wait until there is space in the FIFO + */ + while (read32(base + UART_FR) & UART_FR_TXFF) + ; + + /* Send the character */ + write32(ch, base + UART_DR); +} + +bool uart_have_rx_data(vaddr_t base) +{ + return !(read32(base + UART_FR) & UART_FR_RXFE); +} + +int uart_getchar(vaddr_t base) +{ + while (!uart_have_rx_data(base)) + ; + return read32(base + UART_DR) & 0xff; +} + diff --git a/core/include/asm.S b/core/include/asm.S new file mode 100644 index 00000000000..0a654bdb868 --- /dev/null +++ b/core/include/asm.S @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + .macro FUNC name colon + .global \name + .type \name , %function + \name \colon + .endm + + .macro DATA name colon + .global \name + .type \name , %object + \name \colon + .endm + + .macro LOCAL_FUNC name colon + .type \name , %function + \name \colon + .endm + + .macro LOCAL_DATA name colon + .type \name , %object + \name \colon + .endm + + .macro END_DATA name + .size \name , .-\name + .endm + + .macro END_FUNC name + .size \name , .-\name + .endm diff --git a/core/include/core_serviceid.h b/core/include/core_serviceid.h new file mode 100644 index 00000000000..4356464c469 --- /dev/null +++ b/core/include/core_serviceid.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * Secure services identification numbers + * + * Here is given the description of the functions that are called by the + * dispatcher when user requests a service number + */ +typedef enum { + /* For TEE Client API 1.0 */ + SERVICEID_TEE_OPEN_SESSION = 0x11000008, + SERVICEID_TEE_CLOSE_SESSION = 0x11000009, + SERVICEID_TEE_INVOKE_COMMAND = 0x1100000a, + SERVICEID_TEE_REGISTER_RPC = 0x1100000b, + SERVICEID_TEE_SET_SEC_DDR = 0x1100000c, + SERVICEID_TEE_CANCEL_COMMAND = 0x1100000d, + SERVICEID_TEE_REGISTER_MEMORY = 0x1100000e, + SERVICEID_TEE_UNREGISTER_MEMORY = 0x1100000f, + + /* teecore logs and restarts */ + SERVICEID_TEE_DEINIT_CPU = 0x11000010, + SERVICEID_TEE_CRASH_CPU = 0x11000011, + SERVICEID_TEE_SET_CORE_TRACE_LEVEL = 0x11000012, + SERVICEID_TEE_GET_CORE_TRACE_LEVEL = 0x11000013, + SERVICEID_TEE_SET_TA_TRACE_LEVEL = 0x11000014, + SERVICEID_TEE_GET_TA_TRACE_LEVEL = 0x11000015, + SERVICEID_TEE_GET_CORE_STATUS = 0x11000016, + + /* teecore configurations */ + SERVICEID_REGISTER_DEFAULT_SHMEM = 0x11000020, + SERVICEID_UNREGISTER_DEFAULT_SHMEM = 0x11000021, + SERVICEID_TEE_REGISTER_IRQFWD = 0x11000022, + SERVICEID_TEE_UNREGISTER_IRQFWD = 0x11000023, + SERVICEID_GET_SHMEM_START = 0x11000024, + SERVICEID_GET_SHMEM_SIZE = 0x11000025, + SERVICEID_GET_SHMEM_CACHED = 0x11000026, + + SERVICEID_ENABLE_L2CC_MUTEX = 0x20000000, + SERVICEID_DISABLE_L2CC_MUTEX = 0x20000001, + SERVICEID_GET_L2CC_MUTEX = 0x20000002, + SERVICEID_SET_L2CC_MUTEX = 0x20000003, + + SERVICEID_LOAD_TEE = 0x20000004 + +} t_service_id; + + + diff --git a/core/include/drivers/gic.h b/core/include/drivers/gic.h new file mode 100644 index 00000000000..1bf5523670e --- /dev/null +++ b/core/include/drivers/gic.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GIC_H +#define GIC_H +#include + +void gic_init(paddr_t gicc_base, paddr_t gicd_base); + +void gic_it_add(size_t it); +void gic_it_set_cpu_mask(size_t it, uint8_t cpu_mask); +void gic_it_set_prio(size_t it, uint8_t prio); +void gic_it_enable(size_t it); +void gic_it_disable(size_t it); + +uint32_t gic_read_iar(void); +void gic_write_eoir(uint32_t eoir); + +#endif /*GIC_H*/ + diff --git a/core/include/drivers/uart.h b/core/include/drivers/uart.h new file mode 100644 index 00000000000..ca263a5773a --- /dev/null +++ b/core/include/drivers/uart.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014, Linaro Limited + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef UART_H +#define UART_H + +#include + +void uart_init(vaddr_t base); + +void uart_putc(int ch, vaddr_t base); + +void uart_flush_tx_fifo(vaddr_t base); + +bool uart_have_rx_data(vaddr_t base); + +int uart_getchar(vaddr_t base); + +#endif /*UART_H*/ + diff --git a/core/include/io.h b/core/include/io.h new file mode 100644 index 00000000000..be3702749ae --- /dev/null +++ b/core/include/io.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014, Linaro Limited + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef IO_H +#define IO_H + +static inline void write8(uint8_t val, vaddr_t addr) +{ + *(volatile uint8_t *)addr = val; +} + +static inline void write16(uint16_t val, vaddr_t addr) +{ + *(volatile uint16_t *)addr = val; +} + +static inline void write32(uint32_t val, vaddr_t addr) +{ + *(volatile uint32_t *)addr = val; +} + +static inline uint8_t read8(vaddr_t addr) +{ + return *(volatile uint8_t *)addr; +} + +static inline uint16_t read16(vaddr_t addr) +{ + return *(volatile uint16_t *)addr; +} + +static inline uint32_t read32(vaddr_t addr) +{ + return *(volatile uint32_t *)addr; +} + +#endif /*IO_H*/ diff --git a/core/include/kernel/chip_services.h b/core/include/kernel/chip_services.h new file mode 100644 index 00000000000..41586d165aa --- /dev/null +++ b/core/include/kernel/chip_services.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CHIP_SERVICES_H +#define CHIP_SERVICES_H + +#include +#include + + +#include + +/* Die ID */ +#define FVR_DIE_ID_NUM_REGS 3 + +/*----------------------------------------------------------------------------- + PUBLIC FUNCTION PROTOTYPES + *---------------------------------------------------------------------------*/ +void enable_secure_wd(void); + +#endif diff --git a/core/include/kernel/kernel.h b/core/include/kernel/kernel.h new file mode 100644 index 00000000000..7bad5b837e3 --- /dev/null +++ b/core/include/kernel/kernel.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef KERNEL_KERNEL_H +#define KERNEL_KERNEL_H + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +/* Round up the even multiple of size, size has to be a multiple of 2 */ +#define ROUNDUP(v, size) (((v) + (size - 1)) & ~(size - 1)) + +/* Round down the even multiple of size, size has to be a multiple of 2 */ +#define ROUNDDOWN(v, size) ((v) & ~(size - 1)) + +#endif /*KERNEL_KERNEL_H*/ diff --git a/core/include/kernel/kta_mem.h b/core/include/kernel/kta_mem.h new file mode 100644 index 00000000000..1291038a56b --- /dev/null +++ b/core/include/kernel/kta_mem.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef KTA_MEM_H +#define KTA_MEM_H + +#include +#include + +#define TEE_MEM_SEC_ESRAM_SHIFT 0 +#define TEE_MEM_SEC_CLASS0_DDR_SHIFT 2 +#define TEE_MEM_SEC_CLASS1_DDR_SHIFT 4 +#define TEE_MEM_DDR_SHIFT 6 +#define TEE_MEM_SEC_HW_SHIFT 8 +#define TEE_MEM_RES_MMU_UL1_SHIFT 10 +#define TEE_MEM_MM_ESRAM_FW_SHIFT 12 + +/* Checking for Secure eSRAM */ +#define TEE_MEM_SEC_ESRAM (1 << TEE_MEM_SEC_ESRAM_SHIFT) +#define TEE_MEM_NOT_SEC_ESRAM (TEE_MEM_SEC_ESRAM << 1) +/* Checking for class0 firewalled DDR */ +#define TEE_MEM_SEC_CLASS0_DDR (1 << TEE_MEM_SEC_CLASS0_DDR_SHIFT) +#define TEE_MEM_NOT_SEC_CLASS0_DDR (TEE_MEM_SEC_CLASS0_DDR << 1) +/* Checking for class1 firewalled DDR */ +#define TEE_MEM_SEC_CLASS1_DDR (1 << TEE_MEM_SEC_CLASS1_DDR_SHIFT) +#define TEE_MEM_NOT_SEC_CLASS1_DDR (TEE_MEM_SEC_CLASS1_DDR << 1) +/* Checking for DDR */ +#define TEE_MEM_DDR (1 << TEE_MEM_DDR_SHIFT) +#define TEE_MEM_NOT_DDR (TEE_MEM_DDR << 1) +/* + * Checking for secure resources based on ROM:ed MMU mapping with a few + * exceptions. + */ +#define TEE_MEM_SEC_HW (1 << TEE_MEM_SEC_HW_SHIFT) +#define TEE_MEM_NOT_SEC_HW (TEE_MEM_SEC_HW << 1) + +#define TEE_MEM_RES_MMU_UL1 (1 << TEE_MEM_RES_MMU_UL1_SHIFT) +#define TEE_MEM_NOT_RES_MMU_UL1 (TEE_MEM_RES_MMU_UL1 << 1) +#define TEE_MEM_MM_ESRAM_FW (1 << TEE_MEM_MM_ESRAM_FW_SHIFT) +#define TEE_MEM_NOT_MM_ESRAM_FW (TEE_MEM_MM_ESRAM_FW << 1) + +/* Buffer is non secure, writing to it can't compromise security */ +#define TEE_MEM_NON_SEC (TEE_MEM_NOT_SEC_ESRAM | \ + TEE_MEM_NOT_SEC_CLASS0_DDR | \ + TEE_MEM_NOT_SEC_CLASS1_DDR | \ + TEE_MEM_NOT_SEC_HW | \ + TEE_MEM_NOT_MM_ESRAM_FW) + +/* Buffer is secure, data can't be accessed by normal world */ +#define TEE_MEM_SEC (TEE_MEM_SEC_ESRAM | TEE_MEM_SEC_CLASS0_DDR) + +/* IO access macro */ +#define IO(addr) (*((volatile unsigned long *)(addr))) + +#endif /* KTA_MEM_H */ diff --git a/core/include/kernel/panic.h b/core/include/kernel/panic.h new file mode 100644 index 00000000000..9ebc1212829 --- /dev/null +++ b/core/include/kernel/panic.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef KERNEL_PANIC_H +#define KERNEL_PANIC_H + +#define panic() __panic(__FILE__, __LINE__, __func__) + +void __panic(const char *file, int line, const char *func) + __attribute__((noreturn)); + +#endif /*KERNEL_PANIC_H*/ diff --git a/core/include/kernel/tee_common.h b/core/include/kernel/tee_common.h new file mode 100644 index 00000000000..9b4c4248c9a --- /dev/null +++ b/core/include/kernel/tee_common.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_COMMON_H +#define TEE_COMMON_H + +#include +#include + +#ifdef MEASURE_TIME +/* + * Initializes mesaure time. Initializes RTT0 to highest possible + * resolution. + */ +void tee_mtime_init(void); + +/* + * Adds a time stamp together the description. Note that only the pointer + * is copied, not the contents to minimize impact. + */ +void tee_mtime_stamp(const char *descr); + +/* + * Prints a report of measured times and reinitializes clears the table of + * saved time stamps. + */ +void tee_mtime_report(void); + +void tee_mtime_perftest(void); +#else +/* Empty macros to not have any impact on code when not meassuring time */ +#define tee_mtime_init() do { } while (0) +#define tee_mtime_stamp(descr) do { } while (0) +#define tee_mtime_report() do { } while (0) +#define tee_mtime_perftest() do { } while (0) +#endif + +/* + * Adds physical pages to the pager to use. The supplied virtual address range + * is searched for mapped physical pages and unmapped pages are ignored. + * + * vaddr is the first virtual address + * npages is the number of pages to add + */ +void tee_pager_add_pages(tee_vaddr_t vaddr, size_t npages); + +void tee_pager_unhide_all_pages(void); + +void tee_pager_unmap(uint32_t page, uint8_t psize); + +#endif /* TEE_COMMON_H */ diff --git a/core/include/kernel/tee_common_otp.h b/core/include/kernel/tee_common_otp.h new file mode 100644 index 00000000000..9d291016e59 --- /dev/null +++ b/core/include/kernel/tee_common_otp.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_COMMON_OTP_H +#define TEE_COMMON_OTP_H + +#include "stddef.h" +#include "stdint.h" +#include +#include + +struct tee_hw_unique_key { + uint8_t data[HW_UNIQUE_KEY_LENGTH]; +}; + +/* exposed to let tee_init set the key */ +extern uint8_t hw_key_digest[TEE_SHA256_HASH_SIZE]; + +void tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey); +int tee_otp_get_die_id(uint8_t *buffer, size_t len); + +#endif /* TEE_COMMON_OTP_H */ diff --git a/core/include/kernel/tee_common_unpg.h b/core/include/kernel/tee_common_unpg.h new file mode 100644 index 00000000000..e03d9b98da9 --- /dev/null +++ b/core/include/kernel/tee_common_unpg.h @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_COMMON_UNPG_H +#define TEE_COMMON_UNPG_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef MAX +#define MAX(a, b) \ + (__extension__({ __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a > _b ? _a : _b; })) + +#define MIN(a, b) \ + (__extension__({ __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a < _b ? _a : _b; })) +#endif + +#define TEE_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) + +#define TEE_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + +typedef uintptr_t tee_paddr_t; +/* Compat */ +#define tee_phys_addr_t tee_paddr_t + +typedef uintptr_t tee_vaddr_t; +/* Virtual address valid in user mode */ +typedef uintptr_t tee_uaddr_t; + +/* Round up the even multiple of size, size has to be a multiple of 2 */ +#define TEE_ROUNDUP(v, size) (((v) + (size - 1)) & ~(size - 1)) + +/* Round down the even multiple of size, size has to be a multiple of 2 */ +#define TEE_ROUNDDOWN(v, size) ((v) & ~(size - 1)) + +#if (CFG_TEE_FW_DEBUG == 0) + +#define TEE_ASSERT(expr) \ + do { \ + if (!(expr)) { \ + DMSG("assertion failed"); \ + while (1) \ + ; \ + } \ + } while (0) + +#else + +#define TEE_ASSERT(expr) \ + do { \ + if (!(expr)) { \ + EMSG("assertion '%s' failed at %s:%d (func '%s')", \ + #expr, __FILE__, __LINE__, __func__); \ + while (1) \ + ; \ + } \ + } while (0) + +#endif + +#define TEE_ASSERT_ALIGNMENT(p, type) \ + TEE_ASSERT(TEE_ALIGNMENT_IS_OK(p, type)) + +#ifndef TEE_ALIGNMENT_IS_OK +#ifdef CFG_TC_NO_ALIGNOF +#define TEE_ALIGNMENT_1B_IS_OK(p, type) (true) +#define TEE_ALIGNMENT_2B_IS_OK(p, type) ((&(p) & 1 == 0) ? true : false) +#define TEE_ALIGNMENT_4B_IS_OK(p, type) ((&(p) & 3 == 0) ? true : false) +#define TEE_ALIGNMENT_8B_IS_OK(p, type) ((&(p) & 7 == 0) ? true : false) +#define TEE_ALIGNMENT_IS_OK(p, type) TEE_ALIGNMENT_4B_IS_OK(p, type) +#else +#define TEE_ALIGNMENT_1B_IS_OK(p, type) TEE_ALIGNMENT_WRAP_IS_OK(p, type) +#define TEE_ALIGNMENT_2B_IS_OK(p, type) TEE_ALIGNMENT_WRAP_IS_OK(p, type) +#define TEE_ALIGNMENT_4B_IS_OK(p, type) TEE_ALIGNMENT_WRAP_IS_OK(p, type) +#define TEE_ALIGNMENT_8B_IS_OK(p, type) TEE_ALIGNMENT_WRAP_IS_OK(p, type) +#define TEE_ALIGNMENT_IS_OK(p, type) TEE_ALIGNMENT_WRAP_IS_OK(p, type) + +#define TEE_ALIGNMENT_WRAP_IS_OK(p, type) \ + (((uintptr_t)p & (__tee_assert_alignof__(type) - 1)) == 0) + +#define __tee_assert_alignof__(type) __alignof__(type) +#endif +#endif + +#define TEE_COMPILE_TIME_ASSERT(x) { \ + switch (0) { \ + case 0: \ + ; \ + case ((x) ? 1: 0) : \ + ; \ + default: \ + break; \ + } \ + } + +/*----------------------------------------------------------------------------- + * tee_ta_load_page - Loads a page at address va_addr + * Parameters: + * va_addr - The address somewhere in the page to be loaded (in) + * Returns: + * A session handle to the session related to the memory accessed + * NOTE: This function is executed in abort mode. Pls take care of stack usage + *---------------------------------------------------------------------------*/ +void *tee_ta_load_page(const uint32_t va_addr); + +/*----------------------------------------------------------------------------- + * tee_ta_check_rw - Checks if a page at va_addr contains rw data which should + * be saved + * Parameters: + * va_addr - The address somewhere in the page to be removed (in) + * session_handle - The session handle of the page + * Returns: + * Returns 1 if the page contains data, 0 otherwise + * NOTE: This function is executed in abort mode. Pls take care of stack usage + *---------------------------------------------------------------------------*/ +uint32_t tee_ta_check_rw(const uint32_t va_addr, const void *session_handle); + +/*----------------------------------------------------------------------------- + * tee_ta_save_rw removes a page at address va_addr + * Parameters: + * va_addr - The address somewhere in the page to be removed (in) + * session_handle - The session handle of the page + * Returns: + * void + * NOTE: This function is executed in abort mode. Pls take care of stack usage + *---------------------------------------------------------------------------*/ +void tee_ta_save_rw(const uint32_t va_addr, const void *session_handle); + +#endif /* TEE_COMMON_UNPG_H */ diff --git a/core/include/kernel/tee_compat.h b/core/include/kernel/tee_compat.h new file mode 100644 index 00000000000..1ad52fb99a0 --- /dev/null +++ b/core/include/kernel/tee_compat.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_COMPAT_H +#define TEE_COMPAT_H + +#include +#include +#include + +typedef struct { + void *buffer; + size_t size; + uint32_t flags; +} TEE_SharedMemory; + +typedef struct { + uint32_t param_types; + TEE_Param params[4]; + TEE_SharedMemory memRefs[4]; + uint32_t flags; +} TEE_Operation; + +TEE_Result tee_compat_param_old_to_new(TEE_Operation *op, + struct tee_ta_param *param); + +TEE_Result tee_compat_param_new_to_old(const struct tee_ta_param *param, + TEE_Operation *op); + +#endif /* TEE_COMPAT_H */ diff --git a/core/include/kernel/tee_core_trace.h b/core/include/kernel/tee_core_trace.h new file mode 100644 index 00000000000..95bda6029f7 --- /dev/null +++ b/core/include/kernel/tee_core_trace.h @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_CORE_TRACE_H +#define TEE_CORE_TRACE_H + +#include + +/*****************************************************************************/ + +#if (CFG_TEE_CORE_LOG_LEVEL > 0) +extern int _trace_level; +#endif + +/*****************************************************************************/ + +#ifndef STR_TRACE_CORE +#define STR_TRACE_CORE "TEE-CORE" +#endif + +/*****************************************************************************/ +/* Trace api with trace formatting */ + +/* Filtering and call backend method */ +#define dprintf(level, ...) \ + do { \ + if ((level) <= _trace_level) { \ + _dprintf(__func__, __LINE__, \ + level, STR_TRACE_CORE, __VA_ARGS__); \ + } \ + } while (0) + +/* Formatted trace tagged with TRACE_ALWAYS level */ +#if (CFG_TEE_CORE_LOG_LEVEL < TRACE_ALWAYS) +#define AMSG(...) (void)0 +#else +#define AMSG(...) \ + _dprintf(__func__, __LINE__, TRACE_ALWAYS, STR_TRACE_CORE, __VA_ARGS__); +#endif + +/* Formatted trace tagged with TRACE_ERROR level */ +#if (CFG_TEE_CORE_LOG_LEVEL < TRACE_ERROR) +#define EMSG(...) (void)0 +#else +#define EMSG(...) dprintf(TRACE_ERROR, __VA_ARGS__) +#endif + +/* Formatted trace tagged with TRACE_INFO level */ +#if (CFG_TEE_CORE_LOG_LEVEL < TRACE_INFO) +#define IMSG(...) (void)0 +#else +#define IMSG(...) dprintf(TRACE_INFO, __VA_ARGS__) +#endif + +/* Formatted trace tagged with TRACE_DEBUG level */ +#if (CFG_TEE_CORE_LOG_LEVEL < TRACE_DEBUG) +#define DMSG(...) (void)0 +#else +#define DMSG(...) dprintf(TRACE_DEBUG, __VA_ARGS__) +#endif + +/* Formatted trace tagged with TRACE_FLOW level */ +#if (CFG_TEE_CORE_LOG_LEVEL < TRACE_FLOW) +#define FMSG(...) (void)0 +#else +#define FMSG(...) dprintf(TRACE_FLOW, __VA_ARGS__) +#endif + +/* Formatted trace tagged with TRACE_FLOW level and prefix with '> ' */ +#define INMSG(...) FMSG("> " __VA_ARGS__) +/* Formatted trace tagged with TRACE_FLOW level and prefix with '< ' */ +#define OUTMSG(...) FMSG("< " __VA_ARGS__) +/* Formatted trace tagged with TRACE_FLOW level and prefix with '< ' and print + * an error message if r != 0 */ +#define OUTRMSG(r) \ + do { \ + OUTMSG("r=[%lx]", r); \ + return r; \ + } while (0) + +/*****************************************************************************/ +/* Trace api without trace formatting */ + +#define dprintf_raw(level, ...) \ + do { \ + if ((level) <= _trace_level) { \ + _dprintf(NULL, 0, level, STR_TRACE_CORE, __VA_ARGS__); \ + } \ + } while (0) + +/* No formatted trace tagged with TRACE_ALWAYS level */ +#if (CFG_TEE_CORE_LOG_LEVEL < TRACE_ALWAYS) +#define AMSG_RAW(...) (void)0 +#else +#define AMSG_RAW(...) \ + _dprintf(NULL, 0, TRACE_ALWAYS, STR_TRACE_CORE, __VA_ARGS__) +#endif + +/* No formatted trace tagged with TRACE_ERROR level */ +#if (CFG_TEE_CORE_LOG_LEVEL < TRACE_ERROR) +#define EMSG_RAW(...) (void)0 +#else +#define EMSG_RAW(...) dprintf_raw(TRACE_ERROR, __VA_ARGS__) +#endif + +/* No formatted trace tagged with TRACE_INFO level */ +#if (CFG_TEE_CORE_LOG_LEVEL < TRACE_INFO) +#define IMSG_RAW(...) (void)0 +#else +#define IMSG_RAW(...) dprintf_raw(TRACE_INFO, __VA_ARGS__) +#endif + +/* No formatted trace tagged with TRACE_DEBUG level */ +#if (CFG_TEE_CORE_LOG_LEVEL < TRACE_DEBUG) +#define DMSG_RAW(...) (void)0 +#else +#define DMSG_RAW(...) dprintf_raw(TRACE_DEBUG, __VA_ARGS__) +#endif + +/* No formatted trace tagged with TRACE_FLOW level */ +#if (CFG_TEE_CORE_LOG_LEVEL < TRACE_FLOW) +#define FMSG_RAW(...) (void)0 +#else +#define FMSG_RAW(...) dprintf_raw(TRACE_FLOW, __VA_ARGS__) +#endif + +#if (CFG_TEE_CORE_LOG_LEVEL == 0) +#define SMSG(...) (void)0 +static inline void set_trace_level(int level) { } +static inline int get_trace_level(void) { return 0; } +static inline void core_trace_test(void) { } +#else +/* + * Synchronised flushed trace, an Always message straight to HW trace IP. + * Current only supported inside teecore (not in kernel or user TA). + */ +#define SMSG(...) _dprintf_hwsync(__func__, __LINE__, __VA_ARGS__) +int _dprintf_hwsync(const char *function, int line, const char *fmt, + ...) __PRINTFLIKE(3, 4); + +/* Accessors */ +void set_trace_level(int level); +int get_trace_level(void); +void core_trace_test(void); + +#endif /* CFG_TEE_CORE_LOG_LEVEL */ + +#endif /* TEE_CORE_TRACE_H */ diff --git a/core/include/kernel/tee_customer_part.h b/core/include/kernel/tee_customer_part.h new file mode 100644 index 00000000000..c38fddc48f1 --- /dev/null +++ b/core/include/kernel/tee_customer_part.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TEE_CUSTOMER_PART_H +#define TEE_CUSTOMER_PART_H + +#include "stdint.h" +#include "stdbool.h" +#include "tee_api_types.h" + +#define TEE_SIGNING_CONSTRAINTS_LEN 64 + +TEE_Result tee_cust_part_import(const uint32_t cust_part, + const uint32_t cust_size, + const uint8_t *hash, const uint32_t hash_type); + +#endif /* TEE_CUSTOMER_PART_H */ diff --git a/core/include/kernel/tee_dispatch.h b/core/include/kernel/tee_dispatch.h new file mode 100644 index 00000000000..c9f596961a6 --- /dev/null +++ b/core/include/kernel/tee_dispatch.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_DISPATCH_H +#define TEE_DISPATCH_H + +#include +#include +#include + +#include + + +/* + * output argument data structure is always TEE service specific but always + * starts with the generic output data structure tee_dispatch_out. + */ +struct tee_dispatch_out { + uint32_t duration; + TEE_Result res; + TEE_ErrorOrigin err; +}; + +/* Input arg structure specific to TEE service 'open session'. */ +struct tee_dispatch_open_session_in { + kta_signed_header_t *ta; + TEE_UUID uuid; + uint32_t param_types; + TEE_Param params[4]; + TEE_Identity clnt_id; + uint32_t param_attr[4]; +}; + +/* Output arg structure specific to TEE service 'open session'. */ +struct tee_dispatch_open_session_out { + struct tee_dispatch_out msg; + TEE_Session *sess; + TEE_Param params[4]; +}; + +/* Input arg structure specific to TEE service 'invoke command'. */ +struct tee_dispatch_invoke_command_in { + TEE_Session *sess; + uint32_t cmd; + uint32_t param_types; + TEE_Param params[4]; + uint32_t param_attr[4]; +}; + +/* Output arg structure specific to TEE service 'invoke command'. */ +struct tee_dispatch_invoke_command_out { + struct tee_dispatch_out msg; + TEE_Param params[4]; +}; + +/* Input arg structure specific to TEE service 'cancel command'. */ +struct tee_dispatch_cancel_command_in { + TEE_Session *sess; +}; + +/* Output arg structure specific to TEE service 'cancel command'. */ +struct tee_dispatch_cancel_command_out { + struct tee_dispatch_out msg; +}; + +/* Input arg structure specific to TEE service 'close session'. */ +struct tee_close_session_in { + uint32_t sess; +}; + +/* Input arg structure specific to TEE service 'register shared memory'. */ +struct tee_dispatch_memory_in { + void *buffer; + uint32_t size; +}; + +#if (CFG_TEE_TA_LOG_LEVEL > 0) +/* Input arg structure specific to TEE service 'get XXX trace level'. */ +struct tee_dispatch_set_trace_level_in { + int level; +}; + +/* Output arg structure specific to TEE service 'get XXX trace level'. */ +struct tee_dispatch_get_trace_level_out { + struct tee_dispatch_out msg; + int trace_level; +}; +#endif + +#if (CFG_TEE_FW_DEBUG == 1) +/* Output arg structure specific to TEE service 'get core status'. */ +struct tee_core_status_out { + struct tee_dispatch_out msg; + char raw[80]; +}; +#endif /* CFG_TEE_FW_DEBUG */ + +TEE_Result tee_dispatch_open_session(struct tee_dispatch_open_session_in *in, + struct tee_dispatch_open_session_out *out); +TEE_Result tee_dispatch_close_session(struct tee_close_session_in *in); +TEE_Result tee_dispatch_invoke_command(struct tee_dispatch_invoke_command_in + *in, + struct tee_dispatch_invoke_command_out + *out); +TEE_Result tee_dispatch_cancel_command(struct tee_dispatch_cancel_command_in + *in, + struct tee_dispatch_cancel_command_out + *out); + +#endif /* TEE_DISPATCH_H */ diff --git a/core/include/kernel/tee_kta_trace.h b/core/include/kernel/tee_kta_trace.h new file mode 100644 index 00000000000..102d13ca083 --- /dev/null +++ b/core/include/kernel/tee_kta_trace.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_KTA_TRACE_H +#define TEE_KTA_TRACE_H + +#include + +/*****************************************************************************/ + +extern int _ta_trace_level; + +/*****************************************************************************/ + +#ifndef STR_TRACE_KERNEL_TA +#define STR_TRACE_KERNEL_TA "KERNEL-TA" +#endif + +/*****************************************************************************/ +/* Trace api with trace formatting */ + +/* Filtering and call backend method */ +#define tadprintf(level, ...) \ + do { \ + if ((level) <= _ta_trace_level) { \ + _dprintf(__func__, __LINE__, level, \ + STR_TRACE_KERNEL_TA, __VA_ARGS__); \ + } \ + } while (0) + +/* Formatted trace tagged with TRACE_ALWAYS level */ +#if (CFG_TEE_TA_LOG_LEVEL < TRACE_ALWAYS) +#define ATAMSG(...) (void)0 +#else +#define ATAMSG(...) \ +_dprintf(__func__, __LINE__, TRACE_ALWAYS, STR_TRACE_KERNEL_TA, __VA_ARGS__); +#endif + +/* Formatted trace tagged with TRACE_ERROR level */ +#if (CFG_TEE_TA_LOG_LEVEL < TRACE_ERROR) +#define ETAMSG(...) (void)0 +#else +#define ETAMSG(...) tadprintf(TRACE_ERROR, __VA_ARGS__) +#endif + +/* Formatted trace tagged with TRACE_INFO level */ +#if (CFG_TEE_TA_LOG_LEVEL < TRACE_INFO) +#define ITAMSG(...) (void)0 +#else +#define ITAMSG(...) tadprintf(TRACE_INFO, __VA_ARGS__) +#endif + +/* Formatted trace tagged with TRACE_DEBUG level */ +#if (CFG_TEE_TA_LOG_LEVEL < TRACE_DEBUG) +#define DTAMSG(...) (void)0 +#else +#define DTAMSG(...) tadprintf(TRACE_DEBUG, __VA_ARGS__) +#endif + +/* Formatted trace tagged with TRACE_FLOW level */ +#if (CFG_TEE_TA_LOG_LEVEL < TRACE_FLOW) +#define FTAMSG(...) (void)0 +#else +#define FTAMSG(...) tadprintf(TRACE_FLOW, __VA_ARGS__) +#endif + +/* Formatted trace tagged with TRACE_FLOW level and prefix with '> ' */ +#define TAINMSG(...) FTAMSG("> " __VA_ARGS__) +/* Formatted trace tagged with TRACE_FLOW level and prefix with '< ' */ +#define TAOUTMSG(...) FTAMSG("< " __VA_ARGS__) +/* Formatted trace tagged with TRACE_FLOW level and prefix with '< ' and print + * an error message if r != 0 */ +#define TAOUTRMSG(r) \ + do { \ + OUTMSG("r=[%lx]", r); \ + return r; \ + } while (0) + +/*****************************************************************************/ +/* Trace api without trace formatting */ + +/* Filtering and call backend method */ +#define tadprintf_raw(level, ...) \ + do { \ + if ((level) <= _ta_trace_level) { \ + _dprintf(NULL, 0, level, STR_TRACE_KERNEL_TA, \ + __VA_ARGS__); \ + } \ + } while (0) + +/* No formatted trace tagged with TRACE_ALWAYS level */ +#if (CFG_TEE_TA_LOG_LEVEL < TRACE_ALWAYS) +#define ATAMSG_RAW(...) (void)0 +#else +#define ATAMSG_RAW(...) \ + _dprintf(NULL, 0, TRACE_ALWAYS, STR_TRACE_KERNEL_TA, __VA_ARGS__); +#endif + +/* No formatted trace tagged with TRACE_ERROR level */ +#if (CFG_TEE_TA_LOG_LEVEL < TRACE_ERROR) +#define ETAMSG_RAW(...) (void)0 +#else +#define ETAMSG_RAW(...) tadprintf_raw(TRACE_ERROR, __VA_ARGS__) +#endif + +/* No formatted trace tagged with TRACE_INFO level */ +#if (CFG_TEE_TA_LOG_LEVEL < TRACE_INFO) +#define ITAMSG_RAW(...) (void)0 +#else +#define ITAMSG_RAW(...) tadprintf_raw(TRACE_INFO, __VA_ARGS__) +#endif + +/* No formatted trace tagged with TRACE_DEBUG level */ +#if (CFG_TEE_TA_LOG_LEVEL < TRACE_DEBUG) +#define DTAMSG_RAW(...) (void)0 +#else +#define DTAMSG_RAW(...) tadprintf_raw(TRACE_DEBUG, __VA_ARGS__) +#endif + +/* No formatted trace tagged with TRACE_FLOW level */ +#if (CFG_TEE_TA_LOG_LEVEL < TRACE_FLOW) +#define FTAMSG_RAW(...) (void)0 +#else +#define FTAMSG_RAW(...) tadprintf_raw(TRACE_FLOW, __VA_ARGS__) +#endif + +/*****************************************************************************/ + +/* Accessors */ +#if (CFG_TEE_TA_LOG_LEVEL == 0) +static inline void set_ta_trace_level(int level) { } +static inline int get_ta_trace_level(void) { return 0; } +static inline void ta_trace_test(void) { } +#else +void set_ta_trace_level(int level); +int get_ta_trace_level(void); +void ta_trace_test(void); +#endif + +#endif /* TEE_KTA_TRACE_H */ diff --git a/core/include/kernel/tee_misc_unpg.h b/core/include/kernel/tee_misc_unpg.h new file mode 100644 index 00000000000..2bd4c83c223 --- /dev/null +++ b/core/include/kernel/tee_misc_unpg.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_MISC_UNPG_H +#define TEE_MISC_UNPG_H + +#include + +/* value for tee_get_cutid() result */ +#define ORLY2_CUTID_VAL 0x04160AA0 +#define ORLY2_CUTID_MASK 0xFFFFFFF0 + +#define CANNES_CUTID_VAL 0x03050000 +#define CANNES_CUTID_MASK 0xFFFF0000 + +#define CANNES_CUTID_1_VAL 0x03050010 +#define CANNES_CUTID_1_MASK 0xFFFFFFF0 + +#define CANNES_CUTID_2_VAL 0x03050020 +#define CANNES_CUTID_2_MASK 0xFFFFFFF0 + +/* This function returns the cut id of DBB hardware */ +uint32_t tee_get_cutid(void) __attribute__ ((pure)); + +#endif /* TEE_MISC_UNPG_H */ diff --git a/core/include/kernel/tee_rpc.h b/core/include/kernel/tee_rpc.h new file mode 100644 index 00000000000..467b40b66f1 --- /dev/null +++ b/core/include/kernel/tee_rpc.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TEE_RPC_H +#define TEE_RPC_H + +/* + * tee_rpc_invoke cmd definitions + */ +#define TEE_RPC_LOAD_TA 0x10000001 +#define TEE_RPC_FREE_TA 0x10000009 +#define TEE_RPC_RPMB_CMD 0x1000000A +#define TEE_RPC_FS 0x10000010 +#define TEE_RPC_GET_TIME 0x10000011 + +#endif diff --git a/core/include/kernel/tee_rpc_types.h b/core/include/kernel/tee_rpc_types.h new file mode 100644 index 00000000000..482f010bfb9 --- /dev/null +++ b/core/include/kernel/tee_rpc_types.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TEE_RPC_TYPES_H +#define TEE_RPC_TYPES_H + +#include + +struct tee_rpc_load_ta_cmd { + TEE_UUID uuid; + void *va; +}; + +#endif diff --git a/core/include/kernel/tee_sleep_services.h b/core/include/kernel/tee_sleep_services.h new file mode 100644 index 00000000000..d95d59a5882 --- /dev/null +++ b/core/include/kernel/tee_sleep_services.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_SLEEP_SERVICES_H +#define TEE_SLEEP_SERVICES_H + +#include + +/* + * Save/restore registers for before/after sleep. + */ + +TEE_Result tee_sleep_save_restore_vape(bool save); + +#endif diff --git a/core/include/kernel/tee_ta.h b/core/include/kernel/tee_ta.h new file mode 100644 index 00000000000..a25dde919fb --- /dev/null +++ b/core/include/kernel/tee_ta.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TEE_TA_H +#define TEE_TA_H + +#include +#include + +#define TA_HASH_SIZE 32 +#define TA_UUID_CLOCK_SIZE 8 +#define TA_SIGNATURE_SIZE 264 + +#define TA_HEAD_FLAG_MASK 0xFFF00000UL +#define TA_HEAD_GOT_MASK 0xFFFFUL + +/* Trusted Application header */ +typedef struct { + TEE_UUID uuid; + uint32_t nbr_func; + uint32_t ro_size; + uint32_t rw_size; + uint32_t zi_size; + uint32_t rel_dyn_got_size; + uint32_t hash_type; + /* uint32_t prop_tracelevel; */ +} ta_head_t; + +struct ta_rel_dyn { + uint32_t addr; + uint32_t info; +}; + +/*----------------------------------------------------------------------------- + signed header + ta_head_t + ta_func_head_t (1) + ta_func_head_t (2) + ... + ta_func_head_t (N) N = ta_head(_t).nbr_func + func_1 + func_1 + ... + func_N + GOT + find_service_addr + hash_1 + hash_2 + ... + hash_M + *---------------------------------------------------------------------------*/ + +#endif diff --git a/core/include/kernel/tee_ta_manager.h b/core/include/kernel/tee_ta_manager.h new file mode 100644 index 00000000000..44b47741095 --- /dev/null +++ b/core/include/kernel/tee_ta_manager.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TEE_TA_MANAGER_H +#define TEE_TA_MANAGER_H + +#include + +#include "tee_api_types.h" +#include "tee_api_types.h" +#include "tee_ta.h" +#include +#include "tee_ta_manager_unpg.h" +#include "tee_trace.h" + +/*----------------------------------------------------------------------------- + * Initializes virtual memory management by reserving virtual memory for + * memory areas not available TA virtual memroy allocation. + * + * Spare physical pages are passed in the memory range between ta_start and + * ta_spare_end. Spare physical pages are supposed to be mapped with "no + * access" attribute. + * + * All addresses will be rounded up the the next page. + * + * Parameters: + * ro_start - start of read only section for paging, + * ro_end - end of read only section for paging, + * ta_start - start of section used for TA virtual memory + * ta_spare_end - end of spare pages used for paging + * + * Returns: + * void + *---------------------------------------------------------------------------*/ +void tee_ta_vmem_init(tee_vaddr_t ro_start, tee_vaddr_t ro_end, + tee_vaddr_t ta_start, tee_vaddr_t ta_spare_end); + +TEE_Result tee_ta_open_session(TEE_ErrorOrigin *err, + struct tee_ta_session **sess, + struct tee_ta_session_head *open_sessions, + const TEE_UUID *uuid, + const kta_signed_header_t *ta, + const TEE_Identity *clnt_id, + uint32_t cancel_req_to, + struct tee_ta_param *param); + +TEE_Result tee_ta_invoke_command(TEE_ErrorOrigin *err, + struct tee_ta_session *sess, + const TEE_Identity *clnt_id, + uint32_t cancel_req_to, uint32_t cmd, + struct tee_ta_param *param); + +TEE_Result tee_ta_cancel_command(TEE_ErrorOrigin *err, + struct tee_ta_session *sess, + const TEE_Identity *clnt_id); + +/* + * Load a TA via RPC with UUID defined by input param uuid. The virtual + * address of the TA is recieved in out parameter ta + * + * Function is not thread safe + */ +TEE_Result tee_ta_rpc_load(const TEE_UUID *uuid, kta_signed_header_t **ta, + struct tee_ta_nwumap *map, uint32_t *ret_orig); + +/*----------------------------------------------------------------------------- + * Function called to close a TA. + * Parameters: + * id - The session id (in) + * Returns: + * TEE_Result + *---------------------------------------------------------------------------*/ +TEE_Result tee_ta_close_session(uint32_t id, + struct tee_ta_session_head *open_sessions); + +TEE_Result tee_ta_get_current_session(struct tee_ta_session **sess); + +void tee_ta_set_current_session(struct tee_ta_session *sess); + +TEE_Result tee_ta_make_current_session_resident(void); +void tee_ta_unlock_current_session(void); + +TEE_Result tee_ta_get_client_id(TEE_Identity *id); + +/* + * Get pointer of executable part of the TA located in virtual kernel memory + */ +uintptr_t tee_ta_get_exec(const struct tee_ta_ctx *const ctx); + +/* Returns OK is sess is a valid session pointer or static TA */ +TEE_Result tee_ta_verify_session_pointer(struct tee_ta_session *sess, + struct tee_ta_session_head + *open_sessions); + +int tee_ta_set_trace_level(int level); + +#endif diff --git a/core/include/kernel/tee_ta_manager_unpg.h b/core/include/kernel/tee_ta_manager_unpg.h new file mode 100644 index 00000000000..80ac1b5da78 --- /dev/null +++ b/core/include/kernel/tee_ta_manager_unpg.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TEE_TA_MANAGER_UNPG_H +#define TEE_TA_MANAGER_UNPG_H + +#include +#include + +#include +#include +#include +#include +#include "tee_api_types.h" +#include "user_ta_header.h" +#include "tee_trace.h" + +TAILQ_HEAD(tee_ta_session_head, tee_ta_session); +TAILQ_HEAD(tee_ta_ctx_head, tee_ta_ctx); +TAILQ_HEAD(tee_cryp_state_head, tee_cryp_state); +TAILQ_HEAD(tee_obj_head, tee_obj); +TAILQ_HEAD(tee_storage_enum_head, tee_storage_enum); + +/* normal world user mapping if loaded by tee supplicant */ +struct tee_ta_nwumap { + paddr_t ph; + size_t size; +}; + +/* Context of a loaded TA */ +struct tee_ta_ctx { + TAILQ_ENTRY(tee_ta_ctx) link; + /* list of sessions opened by this TA */ + struct tee_ta_session_head open_sessions; + /* List of cryp states created by this TA */ + struct tee_cryp_state_head cryp_states; + /* List of storage objects opened by this TA */ + struct tee_obj_head objects; + /* List of storage enumerators opened by this TA */ + struct tee_storage_enum_head storage_enums; + ta_head_t *head; /* ptr to the ta head in secure memory */ + void *nmem; /* ptr to code and data in normal world mem */ + /* Normal world user mapping of the TA */ + struct tee_ta_nwumap nwumap; + tee_mm_entry_t *mm; /* secure world memory */ + uint32_t smem_size; /* the size of the secure memory */ + uint32_t rw_data; /* rw data stored on heap */ + uint32_t rw_data_usage; /* bitfield with rw data page usage */ + tee_mm_entry_t *mm_heap_stack; /* shared section of heap and stack */ + size_t stack_size; /* size of stack */ + uint32_t load_addr; /* elf load addr (from TAs address space) */ + uint32_t context; /* Context ID of the process */ + tee_mmu_info_t *mmu; /* Saved MMU information (ddr only) */ + uint32_t num_res_funcs; /* number of reserved ta_func_head_t (2 or 0) */ + uint32_t flags; /* TA_FLAGS from sub header */ + uint32_t panicked; /* True if TA has panicked, written from asm */ + uint32_t panic_code; /* Code supplied for panic */ + uint32_t ref_count; /* Reference counter for multi session TA */ + bool locked; /* session is locked and cannot be closed */ + bool busy; /* context is busy and cannot be entered */ + void *ta_time_offs; /* Time reference used by the TA */ + ta_static_head_t *static_ta; /* TA head struct for other cores */ + void *rlhandle; /* private handle for other cores */ +}; + +struct tee_ta_session { + TAILQ_ENTRY(tee_ta_session) link; + struct tee_ta_ctx *ctx; /* TA context */ + /* session of calling TA if != NULL */ + struct tee_ta_session *calling_sess; + TEE_Identity clnt_id; /* Identify of client */ + bool cancel; /* True if TAF is cancelled */ + bool cancel_mask; /* True if cancel is masked */ + TEE_Time cancel_time; /* Time when to cancel the TAF */ + void *user_ctx; /* ??? */ +}; + +struct tee_ta_param { + uint32_t types; + TEE_Param params[4]; + uint32_t param_attr[4]; +}; + +/* Registered contexts */ +extern struct tee_ta_ctx_head tee_ctxes; + +#ifdef CFG_TEE_PAGER + +/*----------------------------------------------------------------------------- + * tee_ta_load_page - Loads a page at address va_addr + * Parameters: + * va_addr - The address somewhere in the page to be loaded (in) + * Returns: + * A session handle to the session related to the memory accessed + * NOTE: This function is executed in abort mode. Pls take care of stack usage + *---------------------------------------------------------------------------*/ +void *tee_ta_load_page(const uint32_t va_addr); + +/*----------------------------------------------------------------------------- + * tee_ta_check_rw - Checks if a page at va_addr contains rw data which should + * be saved + * Parameters: + * va_addr - The address somewhere in the page to be removed (in) + * session_handle - The session handle of the page + * Returns: + * Returns 1 if the page contains data, 0 otherwise + * NOTE: This function is executed in abort mode. Pls take care of stack usage + *---------------------------------------------------------------------------*/ +uint32_t tee_ta_check_rw(const uint32_t va_addr, const void *session_handle); + +/*----------------------------------------------------------------------------- + * tee_ta_save_rw removes a page at address va_addr + * Parameters: + * va_addr - The address somewhere in the page to be removed (in) + * session_handle - The session handle of the page + * Returns: + * void + * NOTE: This function is executed in abort mode. Pls take care of stack usage + *---------------------------------------------------------------------------*/ +void tee_ta_save_rw(const uint32_t va_addr, const void *session_handle); +#endif /* CFG_TEE_PAGER */ + +#endif /* TEE_TA_MANAGER_UNPG_H */ diff --git a/core/include/kernel/tee_ta_static.h b/core/include/kernel/tee_ta_static.h new file mode 100644 index 00000000000..35e68da0360 --- /dev/null +++ b/core/include/kernel/tee_ta_static.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TEE_CORE_TA_STATIC_H +#define _TEE_CORE_TA_STATIC_H + +#include "tee_api_types.h" + +#define TA_CORE_STATIC_UUID { 0xBC765EDE, 0x6724, 0x11DF, \ + {0x8E, 0x12, 0xEC, 0xDB, 0xDF, 0xD7, 0x20, 0x85} } + +#define TA_CORE_GET_PRODUCT_ID 9 +#define TA_CORE_GET_DIE_ID 33 +#define TA_CORE_GET_GLOBALVALUE 50 +#define TA_CORE_SET_GLOBALVALUE 51 +#define TA_CORE_GET_PRODUCT_ID2 0x1010 +#define TA_CORE_SET_GLOBAL_VALUE_ID 0x2020 +#define TA_CORE_GET_GLOBAL_VALUE_ID 0x2021 +#define TA_CORE_CLEAR_GLOBAL_VALUE_ID 0x2022 + +#endif diff --git a/core/include/kernel/tee_time.h b/core/include/kernel/tee_time.h new file mode 100644 index 00000000000..0114a59b0c8 --- /dev/null +++ b/core/include/kernel/tee_time.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TEE_TIME_H +#define TEE_TIME_H + +#include "tee_api_types.h" + +#define TEE_TIME_BOOT_TICKS_HZ 10UL + +/* + * Init boot time and start the secure time init + */ +TEE_Result tee_time_get_sys_time(TEE_Time *time); +TEE_Result tee_time_get_ta_time(const TEE_UUID *uuid, TEE_Time *time); +TEE_Result tee_time_get_ree_time(TEE_Time *time); +TEE_Result tee_time_set_ta_time(const TEE_UUID *uuid, const TEE_Time *time); +void tee_wait_specific(uint32_t milliseconds_delay); + +#endif diff --git a/core/include/kernel/tee_time_unpg.h b/core/include/kernel/tee_time_unpg.h new file mode 100644 index 00000000000..fee23518637 --- /dev/null +++ b/core/include/kernel/tee_time_unpg.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_TIME_UNPG_H +#define TEE_TIME_UNPG_H + +#include + +extern volatile uint32_t tee_time_rtt0_wrap; + +/* Called from ROM patch point whenever an RTT interrupt is detected */ +void tee_time_rtt_interrupt(void); + +#endif /* TEE_TIME_UNPG_H */ diff --git a/core/include/mm/tee_mm.h b/core/include/mm/tee_mm.h new file mode 100644 index 00000000000..293e86f88fb --- /dev/null +++ b/core/include/mm/tee_mm.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TEE_MM_H +#define TEE_MM_H + +#include +#include + +#include "tee_mm_unpg.h" + +/*----------------------------------------------------------------------------- + * Init managed memory area + *---------------------------------------------------------------------------*/ +bool tee_mm_init(tee_mm_pool_t *pool, uint32_t lo, uint32_t hi, uint8_t shift, + uint32_t flags); + +/*----------------------------------------------------------------------------- + * Kill managed memory area + *---------------------------------------------------------------------------*/ +void tee_mm_final(tee_mm_pool_t *pool); + +/*----------------------------------------------------------------------------- + * Allocates size number of bytes in the paged virtual address space + * Returns a handle to the memory. The handle is used as an input to + * the tee_mm_free function. + *---------------------------------------------------------------------------*/ +tee_mm_entry_t *tee_mm_alloc(tee_mm_pool_t *pool, uint32_t size); + +/* Allocate supplied memory range if it's free */ +tee_mm_entry_t *tee_mm_alloc2(tee_mm_pool_t *pool, tee_vaddr_t base, + size_t size); + +/*----------------------------------------------------------------------------- + * Frees the entry in the paged virtual address space pointed to by the + * input parameter p + *---------------------------------------------------------------------------*/ +void tee_mm_free(tee_mm_entry_t *p); + +/*----------------------------------------------------------------------------- + * Returns size in sections or pages + *---------------------------------------------------------------------------*/ +static inline uint32_t tee_mm_get_size(tee_mm_entry_t *p) +{ + return p->size; +} + +/*----------------------------------------------------------------------------- + * Returns offset from start of area in sections or pages + *---------------------------------------------------------------------------*/ +static inline uint32_t tee_mm_get_offset(tee_mm_entry_t *p) +{ + return p->offset; +} + +/* Return size of the mm entry in bytes */ +size_t tee_mm_get_bytes(const tee_mm_entry_t *mm); + +bool tee_mm_addr_is_within_range(tee_mm_pool_t *pool, uint32_t addr); + +bool tee_mm_is_empty(tee_mm_pool_t *pool); + +#endif diff --git a/core/include/mm/tee_mm_unpg.h b/core/include/mm/tee_mm_unpg.h new file mode 100644 index 00000000000..8445c836caf --- /dev/null +++ b/core/include/mm/tee_mm_unpg.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TEE_MM_UNPG_H +#define TEE_MM_UNPG_H + +#include +#include +#include +#include + +/* Define to indicate default pool initiation */ +#define TEE_MM_POOL_NO_FLAGS 0 +/* Flag to indicate that the pool is paged */ +#define TEE_MM_POOL_PAGED (1u << 0) +/* Flag to indicate that memory is allocated from hi address to low address */ +#define TEE_MM_POOL_HI_ALLOC (1u << 1) + +struct _tee_mm_entry_t { + struct _tee_mm_pool_t *pool; + struct _tee_mm_entry_t *next; + uint32_t offset; /* offset in pages/sections */ + uint32_t size; /* size in pages/sections */ +}; +typedef struct _tee_mm_entry_t tee_mm_entry_t; + +struct _tee_mm_pool_t { + tee_mm_entry_t *entry; + uint32_t lo; /* low boundery pf the pool */ + uint32_t hi; /* high boundery pf the pool */ + uint32_t flags; /* Config flags for the pool */ + uint8_t shift; /* size shift */ +}; +typedef struct _tee_mm_pool_t tee_mm_pool_t; + +/* Physical Public DDR pool */ +extern tee_mm_pool_t tee_mm_pub_ddr; + +/* Physical Secure DDR pool */ +extern tee_mm_pool_t tee_mm_sec_ddr; + +/* Virtual eSRAM pool */ +extern tee_mm_pool_t tee_mm_vcore; + +/* + * Returns a pointer to the mm covering the supplied address, + * if no mm is found NULL is returned. + */ +tee_mm_entry_t *tee_mm_find(const tee_mm_pool_t *pool, uint32_t addr); + +/*----------------------------------------------------------------------------- + * Validates that a address (addr) is part of the secure virtual memory + * Returns false if not valid, true if valid + * NOTE: This function is executed in abort mode. Pls take care of stack usage + *---------------------------------------------------------------------------*/ +static inline bool tee_mm_validate(const tee_mm_pool_t *pool, uint32_t addr) +{ + return tee_mm_find(pool, addr) != NULL; +} + +/*----------------------------------------------------------------------------- + * Returns virtual address of start of allocated memory for the mm entry. + *---------------------------------------------------------------------------*/ +uintptr_t tee_mm_get_smem(const tee_mm_entry_t *mm); + +#endif diff --git a/core/include/mm/tee_mmu.h b/core/include/mm/tee_mmu.h new file mode 100644 index 00000000000..eb9b61437f1 --- /dev/null +++ b/core/include/mm/tee_mmu.h @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_MMU_H +#define TEE_MMU_H + +#include +#include + +/*----------------------------------------------------------------------------- + * Allocate context resources like ASID and MMU table information + *---------------------------------------------------------------------------*/ +TEE_Result tee_mmu_init(struct tee_ta_ctx *ctx); + +/*----------------------------------------------------------------------------- + * tee_mmu_final - Release context resources like ASID + *---------------------------------------------------------------------------*/ +void tee_mmu_final(struct tee_ta_ctx *ctx); + +/*----------------------------------------------------------------------------- + * tee_mmu_map - Map parameters, heap, stack and code to user memory map to + * context + *---------------------------------------------------------------------------*/ +TEE_Result tee_mmu_map(struct tee_ta_ctx *ctx, struct tee_ta_param *param); + + +bool tee_mmu_is_vbuf_inside_ta_private(const struct tee_ta_ctx *ctx, + const uint32_t va, size_t size); + +bool tee_mmu_is_vbuf_outside_ta_private(const struct tee_ta_ctx *ctx, + const uint32_t va, size_t size); + +/*----------------------------------------------------------------------------- + * tee_mmu_kernel_to_user - Translate kernel address to user space address + * given the user context + *---------------------------------------------------------------------------*/ +TEE_Result tee_mmu_kernel_to_user(const struct tee_ta_ctx *ctx, + const uint32_t kaddr, uint32_t *uaddr); + +/*----------------------------------------------------------------------------- + * tee_mmu_user_va2pa - Translate virtual user address to physical address + * given the user context + *---------------------------------------------------------------------------*/ +TEE_Result tee_mmu_user_va2pa_helper(const struct tee_ta_ctx *ctx, void *ua, + void **pa); +/* Special macro to avoid breaking strict aliasing rules */ +#ifdef __GNUC__ +#define tee_mmu_user_va2pa(ctx, va, pa) (__extension__ ({ \ + void *_p; \ + TEE_Result _res = tee_mmu_user_va2pa_helper((ctx), (va), &_p); \ + if (_res == TEE_SUCCESS) \ + *(pa) = _p; \ + _res; \ + })) +#else +#define tee_mmu_user_va2pa(ctx, pa, va) \ + tee_mmu_user_va2pa_helper((ctx), (pa), (va)) +#endif + +/*----------------------------------------------------------------------------- + * tee_mmu_user_va2pa - Translate physical address to virtual user address + * given the user context + *---------------------------------------------------------------------------*/ +TEE_Result tee_mmu_user_pa2va_helper(struct tee_ta_ctx *ctx, + void *pa, void **va); +/* Special macro to avoid breaking strict aliasing rules */ +#ifdef __GNUC__ +#define tee_mmu_user_pa2va(ctx, pa, va) (__extension__ ({ \ + void *_p; \ + TEE_Result _res = tee_mmu_user_pa2va_helper((ctx), (pa), &_p); \ + if (_res == TEE_SUCCESS) \ + *(va) = _p; \ + _res; \ + })) +#else +#define tee_mmu_user_pa2va(ctx, pa, va) \ + tee_mmu_user_pa2va_helper((ctx), (pa), (va)) +#endif + +/*----------------------------------------------------------------------------- + * tee_mmu_check_access_rights - + *---------------------------------------------------------------------------*/ +TEE_Result tee_mmu_check_access_rights(struct tee_ta_ctx *ctx, + uint32_t flags, tee_uaddr_t uaddr, + size_t len); + +/*----------------------------------------------------------------------------- + * If ctx is NULL original ROM mapping is restored with ASID 0 + *---------------------------------------------------------------------------*/ +void tee_mmu_set_ctx(struct tee_ta_ctx *const ctx); + +/* Returns virtual address to which TA is loaded */ +uintptr_t tee_mmu_get_load_addr(const struct tee_ta_ctx *const ctx); + +/* init some allocation pools */ +void tee_mmu_kmap_init(void); +void teecore_init_ta_ram(void); +void teecore_init_pub_ram(void); + +/* Maps physical address into kernel space */ +TEE_Result tee_mmu_kmap_helper(tee_paddr_t pa, size_t len, void **va); +/* Special macro to avoid breaking strict aliasing rules */ +#ifdef __GNUC__ +#define tee_mmu_kmap(pa, len, va) (__extension__ ({ \ + void *_p; \ + TEE_Result _res = tee_mmu_kmap_helper((pa), (len), &_p); \ + if (_res == TEE_SUCCESS) \ + *(va) = _p; \ + _res; \ + })) +#else +#define tee_mmu_kmap(va, len, pa) tee_mmu_kmap_helper((va), (len), (pa)) +#endif + +/* + * Unmaps a memory mapping previously established with tee_mmu_kmap(). + * + * Va and len has to be identical to what was supplied/returned from + * tee_mmu_kmap(). + */ +void tee_mmu_kunmap(void *va, size_t len); + +TEE_Result tee_mmu_kmap_pa2va_helper(void *pa, void **va); +/* Special macro to avoid breaking strict aliasing rules */ +#ifdef __GNUC__ +#define tee_mmu_kmap_pa2va(pa, va) (__extension__ ({ \ + void *_p; \ + TEE_Result _res = tee_mmu_kmap_pa2va_helper((pa), &_p); \ + if (_res == TEE_SUCCESS) \ + *(va) = _p; \ + _res; \ + })) +#else +#define tee_mmu_kmap_pa2va(va, pa) tee_mmu_kmap_pa2va_helper((va), (pa)) +#endif + +TEE_Result tee_mmu_kmap_va2pa_helper(void *va, void **pa); +/* Special macro to avoid breaking strict aliasing rules */ +#ifdef __GNUC__ +#define tee_mmu_kmap_va2pa(va, pa) (__extension__ ({ \ + void *_p; \ + TEE_Result _res = tee_mmu_kmap_va2pa_helper((va), &_p); \ + if (_res == TEE_SUCCESS) \ + *(pa) = _p; \ + _res; \ + })) +#else +#define tee_mmu_kmap_va2pa(pa, va) tee_mmu_kmap_va2pa_helper((pa), (va)) +#endif + +bool tee_mmu_kmap_is_mapped(void *va, size_t len); + +bool tee_mmu_is_kernel_mapping(void); + +uint32_t tee_mmu_kmap_get_cache_attr(void *va); +uint32_t tee_mmu_user_get_cache_attr(struct tee_ta_ctx *ctx, void *va); + + +#endif diff --git a/core/include/mm/tee_mmu_io.h b/core/include/mm/tee_mmu_io.h new file mode 100644 index 00000000000..978d11c27aa --- /dev/null +++ b/core/include/mm/tee_mmu_io.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_MMU_MAP_H +#define TEE_MMU_MAP_H + +#include + +/* Maps physical address into kernel space */ +void *tee_mmu_ioremap(uintptr_t pa, size_t len); +/* + * Unmaps a memory mapping previously established with tee_mmu_ioremap(). + */ +void tee_mmu_iounmap(void *va); + +#endif diff --git a/core/include/mm/tee_mmu_types.h b/core/include/mm/tee_mmu_types.h new file mode 100644 index 00000000000..24562d5249f --- /dev/null +++ b/core/include/mm/tee_mmu_types.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_MMU_TYPES_H +#define TEE_MMU_TYPES_H + +#include + +struct _tee_mmu_info_t { + uint32_t *table; + uint32_t size; + uint32_t ta_private_vmem_start; + uint32_t ta_private_vmem_end; +}; +typedef struct _tee_mmu_info_t tee_mmu_info_t; + +#endif diff --git a/core/include/mm/tee_mmu_unpg.h b/core/include/mm/tee_mmu_unpg.h new file mode 100644 index 00000000000..c0b47b46b06 --- /dev/null +++ b/core/include/mm/tee_mmu_unpg.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_MMU_UNPG_H +#define TEE_MMU_UNPG_H + +#include + +struct tee_mmu_mapping { + uint32_t ttbr0; + uint32_t ctxid; +}; + +void tee_mmu_get_map(struct tee_mmu_mapping *map); + +void tee_mmu_set_map(struct tee_mmu_mapping *map); + +/* + * Switch TTBR0 configuration and Context ID (PROCID & ASID) + */ +void tee_mmu_switch(uint32_t ttbr0_base, uint32_t ctxid); + +/* + * Get current ttbr0 configuration + */ +uint32_t tee_mmu_get_ttbr0(void); + +/* + * Get current context id + */ +uint32_t tee_mmu_get_context(void); + +/* + * Invalidate TLB entries given a asid + */ +void tee_mmu_invtlb_asid(uint32_t asid); + +/* + * Invalidate TLB entries + */ +void invalidate_mmu_tlb(void); + +/* + * Virtual to Physical address translation + */ +uint32_t translate_va2pa(uint32_t va); + +#endif /* TEE_MMU_UNPG_H */ diff --git a/core/include/rng_support.h b/core/include/rng_support.h new file mode 100644 index 00000000000..29d3f75098c --- /dev/null +++ b/core/include/rng_support.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __RNG_SUPPORT_H__ +#define __RNG_SUPPORT_H__ + +#include + +uint8_t hw_get_random_byte(void); + +#endif /* __RNG_SUPPORT_H__ */ diff --git a/core/include/tee/tee_acipher.h b/core/include/tee/tee_acipher.h new file mode 100644 index 00000000000..eebfc48fe7b --- /dev/null +++ b/core/include/tee/tee_acipher.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_ACIPHER_H +#define TEE_ACIPHER_H + +#include +#include +#include + + +TEE_Result tee_acipher_gen_rsa_keys(rsa_key *ltc_key, size_t key_size); + +TEE_Result tee_acipher_gen_dh_keys(dh_key *ltc_key, void *q, size_t xbits); + +TEE_Result tee_acipher_gen_dsa_keys(dsa_key *ltc_key, size_t key_size); + +/* + * Public_key is an input big number + * Secret is an output big number + */ +TEE_Result tee_derive_dh_shared_secret( + dh_key *private_key, void *public_key, void *secret); + +TEE_Result tee_acipher_rsadorep( + rsa_key *ltc_key, + const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len); + +TEE_Result tee_acipher_rsaes_decrypt( + uint32_t algo, rsa_key *ltc_key, const uint8_t *label, size_t label_len, + const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len); + +TEE_Result tee_acipher_rsaes_encrypt( + uint32_t algo, rsa_key *ltc_key, const uint8_t *label, size_t label_len, + const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len); + +/* passing salt_len == -1 -> use default value */ +TEE_Result tee_acipher_rsassa_sign( + uint32_t algo, rsa_key *ltc_key, int salt_len, + const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len); + +/* passing salt_len == -1 -> use default value */ +TEE_Result tee_acipher_rsassa_verify( + uint32_t algo, rsa_key *ltc_key, int salt_len, + const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len); + +TEE_Result tee_acipher_dsa_sign( + uint32_t algo, dsa_key *ltc_key, + const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len); + +TEE_Result tee_acipher_dsa_verify( + uint32_t algo, dsa_key *ltc_key, + const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len); + +#endif /* TEE_ACIPHER_H */ diff --git a/core/include/tee/tee_authenc.h b/core/include/tee/tee_authenc.h new file mode 100644 index 00000000000..a6e4759fcab --- /dev/null +++ b/core/include/tee/tee_authenc.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_AUTHENC_H +#define TEE_AUTHENC_H + +#include + +/* + * Algorithms in this files are as specified with the TEE_ALG_XXX from + * TEE Internal API. + */ + +TEE_Result tee_authenc_get_ctx_size(uint32_t algo, size_t *size); + +TEE_Result tee_authenc_init( + void *ctx, uint32_t algo, TEE_OperationMode mode, const uint8_t *key, + size_t key_len, const uint8_t *nonce, + size_t nonce_len, size_t tag_len, size_t aad_len, size_t payload_len); + +TEE_Result tee_authenc_update_aad( + void *ctx, uint32_t algo, TEE_OperationMode mode, + const uint8_t *data, size_t len); + +TEE_Result tee_authenc_update_payload( + void *ctx, uint32_t algo, TEE_OperationMode mode, + const uint8_t *src_data, size_t src_len, uint8_t *dst_data); + +TEE_Result tee_authenc_enc_final( + void *ctx, uint32_t algo, const uint8_t *src_data, + size_t src_len, uint8_t *dst_data, + uint8_t *dst_tag, size_t *dst_tag_len); + +TEE_Result tee_authenc_dec_final( + void *ctx, uint32_t algo, const uint8_t *src_data, + size_t src_len, uint8_t *dst_data, const uint8_t *tag, size_t tag_len); + +void tee_authenc_final(void *ctx, uint32_t algo); + +#endif /* TEE_AUTHENC_H */ diff --git a/core/include/tee/tee_cipher.h b/core/include/tee/tee_cipher.h new file mode 100644 index 00000000000..3f3ae17d8f4 --- /dev/null +++ b/core/include/tee/tee_cipher.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_CIPHER_H +#define TEE_CIPHER_H + +#include + +/* + * Algorithms in this files are as specified with the TEE_ALG_XXX from + * TEE Internal API. + */ + +TEE_Result tee_cipher_get_ctx_size(uint32_t algo, size_t *size); + +TEE_Result tee_cipher_init(void *ctx, uint32_t algo, + TEE_OperationMode mode, const uint8_t *key, + size_t key_len); + +TEE_Result tee_cipher_init2(void *ctx, uint32_t algo, + TEE_OperationMode mode, const uint8_t *key, + size_t key_len, const uint8_t *iv, size_t iv_len); + +TEE_Result tee_cipher_init3(void *ctx, uint32_t algo, + TEE_OperationMode mode, const uint8_t *key1, + size_t key1_len, const uint8_t *key2, + size_t key2_len, const uint8_t *iv, size_t iv_len); + +TEE_Result tee_cipher_update(void *ctx, uint32_t algo, + TEE_OperationMode mode, bool last_block, + const uint8_t *data, size_t len, uint8_t *dst); + +void tee_cipher_final(void *ctx, uint32_t algo); + +TEE_Result tee_cipher_get_block_size(uint32_t algo, size_t *size); + +#endif /* TEE_CIPHER_H */ diff --git a/core/include/tee/tee_fs.h b/core/include/tee/tee_fs.h new file mode 100644 index 00000000000..601362f3ece --- /dev/null +++ b/core/include/tee/tee_fs.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TEE_FS_H +#define TEE_FS_H + +#include +#include + +#define TEE_FS_NAME_MAX 150 + +typedef int tee_fs_off_t; +typedef uint32_t tee_fs_mode_t; +typedef struct tee_fs_dir tee_fs_dir; + +struct tee_fs_dirent { + char *d_name; +}; + +/* + * tee_fs implemets a POSIX like secure file system + */ +int tee_fs_open(const char *file, int flags, ...); + +int tee_fs_close(int fd); + +int tee_fs_read(int fd, void *buf, size_t len); + +int tee_fs_write(int fd, const void *buf, size_t len); + +tee_fs_off_t tee_fs_lseek(int fd, tee_fs_off_t offset, int whence); + +int tee_fs_rename(const char *old, const char *new); + +int tee_fs_unlink(const char *file); + +int tee_fs_ftruncate(int fd, tee_fs_off_t length); + +int tee_fs_mkdir(const char *path, tee_fs_mode_t mode); + +tee_fs_dir *tee_fs_opendir(const char *name); + +int tee_fs_closedir(tee_fs_dir *d); + +struct tee_fs_dirent *tee_fs_readdir(tee_fs_dir *d); + +int tee_fs_rmdir(const char *pathname); + +int tee_fs_access(const char *name, int mode); + +#endif diff --git a/core/include/tee/tee_fs_defs.h b/core/include/tee/tee_fs_defs.h new file mode 100644 index 00000000000..1bf5282c5fa --- /dev/null +++ b/core/include/tee/tee_fs_defs.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TEE_FS_DEFS_H +#define TEE_FS_DEFS_H + +/* + * tee_fs_open + */ +#define TEE_FS_O_RDONLY 0x1 +#define TEE_FS_O_WRONLY 0x2 +#define TEE_FS_O_RDWR 0x4 +#define TEE_FS_O_CREATE 0x8 +#define TEE_FS_O_EXCL 0x10 + +/* + * tee_fs_lseek + */ +#define TEE_FS_SEEK_SET 0x1 +#define TEE_FS_SEEK_END 0x2 +#define TEE_FS_SEEK_CUR 0x4 + +/* + * file modes + */ +#define TEE_FS_S_IWUSR 0x1 +#define TEE_FS_S_IRUSR 0x2 + +/* + * access modes + * X_OK is not supported + */ +#define TEE_FS_R_OK 0x1 +#define TEE_FS_W_OK 0x2 +#define TEE_FS_F_OK 0x4 + +#endif diff --git a/core/include/tee/tee_hash.h b/core/include/tee/tee_hash.h new file mode 100644 index 00000000000..a5991441ffe --- /dev/null +++ b/core/include/tee/tee_hash.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_HASH_H +#define TEE_HASH_H + +#include + +/* + * Algorithms in this files are as specified with the TEE_ALG_XXX from + * TEE Internal API. + */ + +TEE_Result tee_hash_get_digest_size(uint32_t algo, size_t *size); + +/* Returns required size of context for the specified algorithm */ +TEE_Result tee_hash_get_ctx_size(uint32_t algo, size_t *size); + +TEE_Result tee_hash_init(void *ctx, uint32_t algo); + +TEE_Result tee_hash_update(void *ctx, uint32_t algo, + const uint8_t *data, size_t len); + +TEE_Result tee_hash_final(void *ctx, uint32_t algo, + uint8_t *digest, size_t len); + +TEE_Result tee_hash_createdigest(uint32_t algo, const uint8_t *data, + size_t datalen, uint8_t *digest, + size_t digestlen); + +TEE_Result tee_hash_check( + uint32_t algo, + const uint8_t *hash, size_t hash_size, + const uint8_t *data, size_t data_size); + +#endif /* TEE_HASH_H */ diff --git a/core/include/tee/tee_mac.h b/core/include/tee/tee_mac.h new file mode 100644 index 00000000000..b6d27b51125 --- /dev/null +++ b/core/include/tee/tee_mac.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_HMAC_H +#define TEE_HMAC_H + +#include + +/* + * Algorithms in this files are as specified with the TEE_ALG_XXX from + * TEE Internal API. + */ + +TEE_Result tee_mac_get_digest_size(uint32_t algo, size_t *size); + +/* Returns required size of context for the specified algorithm */ +TEE_Result tee_mac_get_ctx_size(uint32_t algo, size_t *size); + +TEE_Result tee_mac_init( + void *ctx, uint32_t algo, const uint8_t *key, size_t len); + +TEE_Result tee_mac_update( + void *ctx, uint32_t algo, const uint8_t *data, size_t len); + +TEE_Result tee_mac_final( + void *ctx, uint32_t algo, + const uint8_t *data, size_t data_len, + uint8_t *digest, size_t digest_len); + +#endif /* TEE_HMAC_H */ diff --git a/core/include/tee/tee_obj.h b/core/include/tee/tee_obj.h new file mode 100644 index 00000000000..b923cb9fd68 --- /dev/null +++ b/core/include/tee/tee_obj.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TEE_OBJ_H +#define TEE_OBJ_H + +#include +#include +#include + +#define TEE_USAGE_DEFAULT 0xffffffff + +struct tee_obj { + TAILQ_ENTRY(tee_obj) link; + TEE_ObjectInfo info; + bool busy; /* true if used by an operation */ + uint32_t have_attrs; /* bitfield identifying set properties */ + void *data; + size_t data_size; + struct tee_pobj *pobj; /* ptr to persistant object */ + int fd; + uint32_t ds_size; /* data stream size */ + uint32_t flags; /* permission flags for persistent objects */ +}; + +void tee_obj_add(struct tee_ta_ctx *ctx, struct tee_obj *o); + +TEE_Result tee_obj_get(struct tee_ta_ctx *ctx, uint32_t obj_id, + struct tee_obj **obj); + +void tee_obj_close(struct tee_ta_ctx *ctx, struct tee_obj *o); + +void tee_obj_close_all(struct tee_ta_ctx *ctx); + +#endif diff --git a/core/include/tee/tee_pobj.h b/core/include/tee/tee_pobj.h new file mode 100644 index 00000000000..f2abcbe4abd --- /dev/null +++ b/core/include/tee/tee_pobj.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TEE_POBJ_H +#define TEE_POBJ_H + +#include +#include +#include + +struct tee_pobj { + TAILQ_ENTRY(tee_pobj) link; + uint32_t refcnt; + TEE_UUID uuid; + void *obj_id; + uint32_t obj_id_len; + uint32_t flags; +}; + +TEE_Result tee_pobj_get(TEE_UUID *uuid, void *obj_id, uint32_t obj_id_len, + uint32_t flags, struct tee_pobj **obj); + +TEE_Result tee_pobj_release(struct tee_pobj *obj); + +TEE_Result tee_pobj_rename(struct tee_pobj *obj, void *obj_id, + uint32_t obj_id_len); + +void tee_pobj_init(void); + +#endif diff --git a/core/include/tee/tee_rpmb.h b/core/include/tee/tee_rpmb.h new file mode 100644 index 00000000000..778341df0fb --- /dev/null +++ b/core/include/tee/tee_rpmb.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TEE_RPMB_H +#define TEE_RPMB_H + +#include "tee_api_types.h" + +/* + * Generate RPMB key and write to eMMC. + * + * @dev_id Device ID of the eMMC device. + * @commercial Flag indicating if we should write + * commercial key which is bound to + * the hard unique key. + */ +TEE_Result tee_rpmb_write_key(uint16_t dev_id, bool commercial); + +/* + * Read RPMB data in bytes. + * + * @dev_id Device ID of the eMMC device. + * @addr Byte address of data. + * @data Pointer to the data. + * @len Size of data in bytes. + */ +TEE_Result tee_rpmb_read(uint16_t dev_id, + uint32_t addr, uint8_t *data, uint32_t len); + +/* + * Write RPMB data in bytes. + * + * @dev_id Device ID of the eMMC device. + * @addr Byte address of data. + * @data Pointer to the data. + * @len Size of data in bytes. + */ +TEE_Result tee_rpmb_write(uint16_t dev_id, + uint32_t addr, uint8_t *data, uint32_t len); + +/* + * Read the RPMB write counter. + * + * @dev_id Device ID of the eMMC device. + * @counter Pointer to the counter. + */ +TEE_Result tee_rpmb_get_write_counter(uint16_t dev_id, uint32_t *counter); +#endif diff --git a/core/include/tee/tee_rpmb_fs.h b/core/include/tee/tee_rpmb_fs.h new file mode 100644 index 00000000000..686e924aa1c --- /dev/null +++ b/core/include/tee/tee_rpmb_fs.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TEE_RPMB_FS_H +#define TEE_RPMB_FS_H + +#include +#include +#include + +#define FILENAME_LENGTH 48 + +struct tee_rpmb_fs_stat { + uint32_t size; + uint32_t reserved; +}; + +/** + * tee_rpmb_fs_read: Read entire file + * Reads data from file pointed to by filename. + * buf should be allocated by the client and its size must >= file size. + * + * Returns number of bytes read from the file or + * a value < 0 on failure. + */ +int tee_rpmb_fs_read(const char *filename, uint8_t *buf, size_t size); + +/** + * tee_rpmb_fs_write: Write data to file + * Write data to an existing file or create a new file and Write data. + * If the file pointed to by filename exists, data will be overwritten, + * otherwise the file will be created. + * size bytes of data will be copied from buf. + * + * Return n bytes written on success or a value < 0 on failure. + */ +int tee_rpmb_fs_write(const char *filename, uint8_t *buf, size_t size); + +/** + * tee_rpmb_fs_rm: Remove a file. + * Only files that belongs to the client can be removed. + */ +TEE_Result tee_rpmb_fs_rm(const char *filename); + +TEE_Result tee_rpmb_fs_rename(const char *old, const char *new); + +TEE_Result tee_rpmb_fs_stat(const char *filename, + struct tee_rpmb_fs_stat *stat); + +#endif diff --git a/core/include/tee/tee_svc.h b/core/include/tee/tee_svc.h new file mode 100644 index 00000000000..213f4a6edc4 --- /dev/null +++ b/core/include/tee/tee_svc.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_SVC_H +#define TEE_SVC_H + +#include +#include /* tee_uaddr_t */ +#include +#include +#include +#include + +struct tee_ta_session; + +void tee_svc_user_ta_panic_from_pager(void); + +/* + * This function will not return itself, rather it will end with a system + * call to return to kernel mode. The syscall will unwinde the stack and + * the result will be as if this function had returned. + * + * User_func is called in user mode with stack setup and a0-a3 passed + * in r0-r3. + */ +TEE_Result tee_svc_enter_user_mode(uint32_t a0, uint32_t a1, uint32_t a2, + uint32_t a3, tee_uaddr_t sp, + tee_uaddr_t user_func, uint32_t *panicked, + uint32_t *panic_code); + +void tee_svc_sys_return(uint32_t ret, uint32_t param_types, void *params); + +void tee_svc_sys_log(const void *buf, size_t len); + +void tee_svc_sys_panic(uint32_t code); +uint32_t tee_svc_sys_dummy(uint32_t *a); +uint32_t tee_svc_sys_dummy_7args(uint32_t a1, uint32_t a2, uint32_t a3, + uint32_t a4, uint32_t a5, uint32_t a6, + uint32_t a7); + +uint32_t tee_svc_sys_nocall(void); + +TEE_Result tee_svc_sys_get_property(uint32_t prop, tee_uaddr_t buf, + size_t blen); + +TEE_Result tee_svc_open_ta_session(const TEE_UUID *dest, + uint32_t cancel_req_to, uint32_t param_types, + TEE_Param params[4], + TEE_TASessionHandle *sess, + uint32_t *ret_orig); + +TEE_Result tee_svc_close_ta_session(TEE_TASessionHandle sess); + +TEE_Result tee_svc_invoke_ta_command(TEE_TASessionHandle sess, + uint32_t cancel_req_to, uint32_t cmd_id, + uint32_t param_types, TEE_Param params[4], + uint32_t *ret_orig); + +TEE_Result tee_svc_check_access_rights(uint32_t flags, const void *buf, + size_t len); + +TEE_Result tee_svc_copy_from_user(struct tee_ta_session *sess, void *kaddr, + const void *uaddr, size_t len); +TEE_Result tee_svc_copy_to_user(struct tee_ta_session *sess, void *uaddr, + const void *kaddr, size_t len); + +TEE_Result tee_svc_get_cancellation_flag(bool *cancel); + +TEE_Result tee_svc_unmask_cancellation(bool *old_mask); + +TEE_Result tee_svc_mask_cancellation(bool *old_mask); + +TEE_Result tee_svc_wait(uint32_t timeout); + +TEE_Result tee_svc_get_time(enum utee_time_category cat, TEE_Time *time); +TEE_Result tee_svc_set_ta_time(const TEE_Time *time); + +#endif /* TEE_SVC_H */ diff --git a/core/include/tee/tee_svc_cryp.h b/core/include/tee/tee_svc_cryp.h new file mode 100644 index 00000000000..bcfcf52a650 --- /dev/null +++ b/core/include/tee/tee_svc_cryp.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_SVC_CRYP_H +#define TEE_SVC_CRYP_H + +#include +#include + +TEE_Result tee_svc_cryp_obj_get_info(uint32_t obj, TEE_ObjectInfo *info); +TEE_Result tee_svc_cryp_obj_restrict_usage(uint32_t obj, uint32_t usage); +TEE_Result tee_svc_cryp_obj_get_attr(uint32_t obj, uint32_t attr_id, + void *buffer, size_t *size); + +TEE_Result tee_svc_cryp_obj_alloc(TEE_ObjectType obj_type, + uint32_t max_obj_size, uint32_t *obj); +TEE_Result tee_svc_cryp_obj_close(uint32_t obj); +TEE_Result tee_svc_cryp_obj_reset(uint32_t obj); +TEE_Result tee_svc_cryp_obj_populate(uint32_t obj, TEE_Attribute *attrs, + uint32_t attr_count); +TEE_Result tee_svc_cryp_obj_copy(uint32_t dst_obj, uint32_t src_obj); +TEE_Result tee_svc_obj_generate_key(uint32_t obj, uint32_t key_size, + const TEE_Attribute *params, + uint32_t param_count); + +TEE_Result tee_svc_cryp_state_alloc(uint32_t algo, uint32_t op_mode, + uint32_t key1, uint32_t key2, + uint32_t *state); +TEE_Result tee_svc_cryp_state_copy(uint32_t dst, uint32_t src); +TEE_Result tee_svc_cryp_state_free(uint32_t state); +void tee_svc_cryp_free_states(struct tee_ta_ctx *ctx); + +/* iv and iv_len are ignored for hash algorithms */ +TEE_Result tee_svc_hash_init(uint32_t state, const void *iv, size_t iv_len); +TEE_Result tee_svc_hash_update(uint32_t state, const void *chunk, + size_t chunk_size); +TEE_Result tee_svc_hash_final(uint32_t state, const void *chunk, + size_t chunk_size, void *hash, size_t *hash_len); + +TEE_Result tee_svc_cipher_init(uint32_t state, const void *iv, size_t iv_len); +TEE_Result tee_svc_cipher_update(uint32_t state, const void *src, + size_t src_len, void *dest, size_t *dest_len); +TEE_Result tee_svc_cipher_final(uint32_t state, const void *src, + size_t src_len, void *dest, size_t *dest_len); + +TEE_Result tee_svc_cryp_derive_key(uint32_t state, const TEE_Attribute *params, + uint32_t param_count, uint32_t derived_key); + +TEE_Result tee_svc_cryp_random_number_generate(void *buf, size_t blen); + +TEE_Result tee_svc_authenc_init(uint32_t state, const void *nonce, + size_t nonce_len, size_t tag_len, + size_t aad_len, size_t payload_len); +TEE_Result tee_svc_authenc_update_aad(uint32_t state, const void *aad_data, + size_t aad_data_len); +TEE_Result tee_svc_authenc_update_payload(uint32_t state, const void *src_data, + size_t src_len, void *dest_data, + size_t *dest_len); +TEE_Result tee_svc_authenc_enc_final(uint32_t state, const void *src_data, + size_t src_len, void *dest_data, + size_t *dest_len, void *tag, + size_t *tag_len); +TEE_Result tee_svc_authenc_dec_final(uint32_t state, const void *src_data, + size_t src_len, void *dest_data, + size_t *dest_len, const void *tag, + size_t tag_len); + +TEE_Result tee_svc_asymm_operate(uint32_t state, const TEE_Attribute *params, + uint32_t num_params, const void *src_data, + size_t src_len, void *dest_data, + size_t *dest_len); +TEE_Result tee_svc_asymm_verify(uint32_t state, const TEE_Attribute *params, + uint32_t num_params, const void *data, + size_t data_len, const void *sig, + size_t sig_len); + +TEE_Result get_rng_array(void *buffer, int len); + +#endif /* TEE_SVC_CRYP_H */ diff --git a/core/include/tee/tee_svc_storage.h b/core/include/tee/tee_svc_storage.h new file mode 100644 index 00000000000..7776e00ef0f --- /dev/null +++ b/core/include/tee/tee_svc_storage.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TEE_SVC_STORAGE_H +#define TEE_SVC_STORAGE_H + +#include +#include + +/* + * Persistant Object Functions + */ +TEE_Result tee_svc_storage_obj_open(uint32_t storage_id, void *object_id, + uint32_t object_id_len, uint32_t flags, + uint32_t *obj); + +TEE_Result tee_svc_storage_obj_create(uint32_t storage_id, void *object_id, + uint32_t object_id_len, uint32_t flags, + uint32_t attr, void *data, uint32_t len, + uint32_t *obj); + +TEE_Result tee_svc_storage_obj_del(uint32_t obj); + +TEE_Result tee_svc_storage_obj_rename(uint32_t obj, void *object_id, + uint32_t object_id_len); + +/* + * Persistent Object Enumeration Functions + */ +TEE_Result tee_svc_storage_alloc_enum(uint32_t *obj_enum); + +TEE_Result tee_svc_storage_free_enum(uint32_t obj_enum); + +TEE_Result tee_svc_storage_reset_enum(uint32_t obj_enum); + +TEE_Result tee_svc_storage_start_enum(uint32_t obj_enum, uint32_t storage_id); + +TEE_Result tee_svc_storage_next_enum(uint32_t obj_enum, TEE_ObjectInfo *info, + void *obj_id, size_t *len); + +/* + * Data Stream Access Functions + */ +TEE_Result tee_svc_storage_obj_read(uint32_t obj, void *data, size_t len, + uint32_t *count); + +TEE_Result tee_svc_storage_obj_write(uint32_t obj, void *data, size_t len); + +TEE_Result tee_svc_storage_obj_trunc(uint32_t obj, size_t len); + +TEE_Result tee_svc_storage_obj_seek(uint32_t obj, int32_t offset, + TEE_Whence whence); + +void tee_svc_storage_close_all_enum(struct tee_ta_ctx *ctx); + +void tee_svc_storage_init(void); + +#endif /* TEE_SVC_STORAGE_H */ diff --git a/core/kernel/assert.c b/core/kernel/assert.c new file mode 100644 index 00000000000..ff7bee8ec2e --- /dev/null +++ b/core/kernel/assert.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include + +/* indirected assert (see TEE_ASSERT()) */ + +void _assert_log(const char *expr, const char *file, int line) +{ + EMSG("Assertion '%s' failed at %s:%d", expr, file, line); +} + +void __attribute__ ((noreturn)) _assert_break(void) +{ + while (1) + ; +} diff --git a/core/kernel/panic.c b/core/kernel/panic.c new file mode 100644 index 00000000000..fde15e3fec7 --- /dev/null +++ b/core/kernel/panic.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +void __panic(const char *file, int line, const char *func) +{ + EMSG("PANIC: %s %s:%d\n", func, file, line); + while (1) + ; +} diff --git a/core/kernel/sub.mk b/core/kernel/sub.mk new file mode 100644 index 00000000000..278e64ed357 --- /dev/null +++ b/core/kernel/sub.mk @@ -0,0 +1,7 @@ +srcs-y += assert.c +cflags-assert.c-y += -Wno-missing-prototypes -Wno-missing-declarations +srcs-y += tee_compat.c +srcs-y += tee_dispatch.c +srcs-y += tee_kta_trace.c +srcs-y += tee_ta_manager_unpg.c +srcs-y += panic.c diff --git a/core/kernel/tee_compat.c b/core/kernel/tee_compat.c new file mode 100644 index 00000000000..477a340c0f1 --- /dev/null +++ b/core/kernel/tee_compat.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +TEE_Result tee_compat_param_old_to_new(TEE_Operation *op, + struct tee_ta_param *param) +{ + size_t n; + uint32_t pt; + + memset(param, 0, sizeof(*param)); + + for (n = 0; n < 4; n++) { + if (op->flags & 1 << n) { + switch (op->memRefs[n].flags) { + case TEE_MEM_INPUT: + pt = TEE_PARAM_TYPE_MEMREF_INPUT; + break; + case TEE_MEM_OUTPUT: + pt = TEE_PARAM_TYPE_MEMREF_OUTPUT; + break; + case TEE_MEM_INPUT | TEE_MEM_OUTPUT: + pt = TEE_PARAM_TYPE_MEMREF_INOUT; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + param->types |= pt << (n * 4); + param->params[n].memref.buffer = op->memRefs[n].buffer; + param->params[n].memref.size = op->memRefs[n].size; + } + } + + return TEE_SUCCESS; +} + +TEE_Result tee_compat_param_new_to_old(const struct tee_ta_param *param, + TEE_Operation *op) +{ + size_t n; + + op->flags = 0; + for (n = 0; n < 4; n++) { + switch (TEE_PARAM_TYPE_GET(param->types, n)) { + case TEE_PARAM_TYPE_NONE: + continue; + + case TEE_PARAM_TYPE_VALUE_INPUT: + case TEE_PARAM_TYPE_VALUE_OUTPUT: + case TEE_PARAM_TYPE_VALUE_INOUT: + return TEE_ERROR_BAD_PARAMETERS; /* Not supported */ + + case TEE_PARAM_TYPE_MEMREF_INPUT: + op->memRefs[n].flags = TEE_MEM_INPUT; + break; + + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + op->memRefs[n].flags = TEE_MEM_OUTPUT; + break; + + case TEE_PARAM_TYPE_MEMREF_INOUT: + op->memRefs[n].flags = TEE_MEM_INPUT | TEE_MEM_OUTPUT; + break; + + default: + return TEE_ERROR_BAD_PARAMETERS; /* Not supported */ + } + + op->flags |= 1 << n; + op->memRefs[n].buffer = param->params[n].memref.buffer; + op->memRefs[n].size = param->params[n].memref.size; + } + + return TEE_SUCCESS; +} diff --git a/core/kernel/tee_dispatch.c b/core/kernel/tee_dispatch.c new file mode 100644 index 00000000000..1a22c4a9a30 --- /dev/null +++ b/core/kernel/tee_dispatch.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#include + +/* Sessions opened from normal world */ +static struct tee_ta_session_head tee_open_sessions = +TAILQ_HEAD_INITIALIZER(tee_open_sessions); + +static void update_out_param(const struct tee_ta_param *in, TEE_Param *out) +{ + size_t n; + + for (n = 0; n < 4; n++) { + switch (TEE_PARAM_TYPE_GET(in->types, n)) { + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + out[n].memref.size = in->params[n].memref.size; + break; + case TEE_PARAM_TYPE_VALUE_OUTPUT: + case TEE_PARAM_TYPE_VALUE_INOUT: + out[n].value = in->params[n].value; + break; + default: + break; + } + } +} + +static TEE_Result update_clnt_id(const TEE_Identity *in, TEE_Identity *out) +{ + /* + * Check that only login types from normal world are allowed. + */ + out->login = in->login; + switch (out->login) { + case TEE_LOGIN_PUBLIC: + case TEE_LOGIN_KERNEL: + memset(&out->uuid, 0, sizeof(TEE_UUID)); + break; + case TEE_LOGIN_USER: + case TEE_LOGIN_GROUP: + case TEE_LOGIN_APPLICATION: + case TEE_LOGIN_APPLICATION_USER: + case TEE_LOGIN_APPLICATION_GROUP: + out->uuid = in->uuid; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + return TEE_SUCCESS; +} + +TEE_Result tee_dispatch_open_session(struct tee_dispatch_open_session_in *in, + struct tee_dispatch_open_session_out *out) +{ + TEE_Result res = TEE_ERROR_BAD_PARAMETERS; + struct tee_ta_session *s = NULL; + uint32_t res_orig = TEE_ORIGIN_TEE; + + struct tee_ta_param *param = malloc(sizeof(struct tee_ta_param)); + TEE_Identity *clnt_id = malloc(sizeof(TEE_Identity)); + + if (param == NULL || clnt_id == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto cleanup_return; + } + + res = update_clnt_id(&in->clnt_id, clnt_id); + if (res != TEE_SUCCESS) + goto cleanup_return; + + param->types = in->param_types; + memcpy(param->params, in->params, sizeof(in->params)); + memcpy(out->params, in->params, sizeof(in->params)); + memcpy(param->param_attr, in->param_attr, sizeof(in->param_attr)); + + res = tee_ta_open_session(&res_orig, &s, &tee_open_sessions, &in->uuid, + in->ta, clnt_id, TEE_TIMEOUT_INFINITE, param); + if (res_orig == TEE_ORIGIN_TEE && res == TEE_ERROR_ITEM_NOT_FOUND) { + kta_signed_header_t *ta = NULL; + struct tee_ta_nwumap lp; + + /* Load TA */ + res = tee_ta_rpc_load(&in->uuid, &ta, &lp, &res_orig); + if (res != TEE_SUCCESS) + goto cleanup_return; + + res = tee_ta_open_session(&res_orig, &s, &tee_open_sessions, + NULL, ta, clnt_id, + TEE_TIMEOUT_INFINITE, param); + if (res != TEE_SUCCESS) + goto cleanup_return; + + s->ctx->nwumap = lp; + + } + if (res != TEE_SUCCESS) + goto cleanup_return; + + out->sess = (TEE_Session *)s; + update_out_param(param, out->params); + +cleanup_return: + if (res != TEE_SUCCESS) + DMSG(" => Error: %x of %d", (unsigned int)res, (int)res_orig); + + free(param); + free(clnt_id); + + out->msg.err = res_orig; + out->msg.res = res; + return res; +} + +TEE_Result tee_dispatch_close_session(struct tee_close_session_in *in) +{ + return tee_ta_close_session(in->sess, &tee_open_sessions); +} + +TEE_Result tee_dispatch_invoke_command(struct tee_dispatch_invoke_command_in * + in, + struct tee_dispatch_invoke_command_out * + out) +{ + struct tee_ta_param param; + struct tee_ta_session *sess; /*= (struct tee_ta_session *)arg->sess; */ + TEE_Result res; + TEE_ErrorOrigin err; + + /* PRINTF("in tee_dispatch_invoke_command\n"); */ + /* PRINTF("arg : %08x\n", (unsigned int)arg); */ + + sess = (struct tee_ta_session *)in->sess; + + res = tee_ta_verify_session_pointer(sess, &tee_open_sessions); + if (res != TEE_SUCCESS) + goto cleanup_return; + + param.types = in->param_types; + memcpy(param.params, in->params, sizeof(in->params)); + memcpy(out->params, in->params, sizeof(in->params)); + memcpy(param.param_attr, in->param_attr, sizeof(in->param_attr)); + + res = tee_ta_invoke_command(&err, sess, NULL, + TEE_TIMEOUT_INFINITE, in->cmd, ¶m); + update_out_param(¶m, out->params); + +cleanup_return: + out->msg.res = res; + out->msg.err = err; + return out->msg.res; +} + +TEE_Result tee_dispatch_cancel_command(struct tee_dispatch_cancel_command_in * + in, + struct tee_dispatch_cancel_command_out * + out) +{ + TEE_Result res = TEE_ERROR_BAD_PARAMETERS; + struct tee_ta_session *sess = (struct tee_ta_session *)in->sess; + uint32_t res_orig = TEE_ORIGIN_TEE; + + res = tee_ta_verify_session_pointer(sess, &tee_open_sessions); + if (res != TEE_SUCCESS) + goto cleanup_return; + + res = tee_ta_cancel_command(&res_orig, sess, NULL); + +cleanup_return: + out->msg.err = res_orig; + out->msg.res = res; + return res; +} diff --git a/core/kernel/tee_kta_trace.c b/core/kernel/tee_kta_trace.c new file mode 100644 index 00000000000..6f68c554dda --- /dev/null +++ b/core/kernel/tee_kta_trace.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include + +/*****************************************************************************/ + +/* Default trace level */ +int _ta_trace_level = CFG_TEE_TA_LOG_LEVEL; + +/*****************************************************************************/ + +void ta_trace_test(void) +{ + TAINMSG("level: [%d]", _ta_trace_level); + ITAMSG("current trace level = %d", _ta_trace_level); + ITAMSG("Without args"); + ATAMSG("[%d] and [%s]", TRACE_ALWAYS, "TRACE_ALWAYS"); + ETAMSG("[%d] and [%s]", TRACE_ERROR, "TRACE_ERROR"); + ITAMSG("[%d] and [%s]", TRACE_INFO, "TRACE_INFO"); + DTAMSG("[%d] and [%s]", TRACE_DEBUG, "TRACE_DEBUG"); + FTAMSG("[%d] and [%s]", TRACE_FLOW, "TRACE_FLOW"); + ATAMSG_RAW("raw trace in KERNEL-TA with level [%s]", "TRACE_ALWAYS"); + ATAMSG_RAW(" __ end of raw trace\n"); + DTAMSG_RAW("raw trace in KERNEL-TA with level [%s]", "TRACE_DEBUG"); + DTAMSG_RAW(" __ end of raw trace\n"); + TAOUTMSG(""); +} + +/*****************************************************************************/ + +void set_ta_trace_level(int level) +{ + if ((level <= CFG_TEE_TA_LOG_LEVEL) && + (level >= TRACE_MIN) && + (level <= TRACE_MAX)) + _ta_trace_level = level; + else { + ATAMSG("Can't set level [%d]", level); + return; + } + + /* parse all loaded TAs to set TA trace level */ + (void)tee_ta_set_trace_level(level); + + ta_trace_test(); + ATAMSG_RAW("\nLevel set to [%d]\n", _ta_trace_level); +} + +int get_ta_trace_level(void) +{ + return _ta_trace_level; +} + +#if (CFG_TEE_CORE_LOG_LEVEL == 0) +/* no log, sorry! implement a dummy _dprintf */ +int _dprintf(const char *function, int line, int level, const char *prefix, + const char *fmt, ...) +{ + return 0; +} +#endif +/*****************************************************************************/ diff --git a/core/kernel/tee_ta_manager_unpg.c b/core/kernel/tee_ta_manager_unpg.c new file mode 100644 index 00000000000..8f518bd9d26 --- /dev/null +++ b/core/kernel/tee_ta_manager_unpg.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +struct tee_ta_ctx_head tee_ctxes = TAILQ_HEAD_INITIALIZER(tee_ctxes); + +/*----------------------------------------------------------------------------- + * Find ta session for a va_addr + * Executed in abort mode + *---------------------------------------------------------------------------*/ +static struct tee_ta_ctx *tee_ta_find_context(const uint32_t va_addr) +{ + struct tee_ta_ctx *ctx; + uintptr_t smem; /* start memory address for session */ + uintptr_t emem; /* end memory address for session */ + + TAILQ_FOREACH(ctx, &tee_ctxes, link) { + smem = tee_mm_get_smem(ctx->mm); + emem = smem + ctx->smem_size; + + /* + * If the address is in the range of virtual memory for this + * session we have found it. + */ + if (va_addr >= smem && va_addr <= emem) + break; + } + return ctx; +} + +/*----------------------------------------------------------------------------- + * Load and verify a page at va_addr + * Executed in abort mode + *---------------------------------------------------------------------------*/ +void *tee_ta_load_page(const uint32_t va_addr) +{ + struct tee_ta_ctx *ts = tee_ta_find_context(va_addr); + uint32_t smem; /* start memory address for session */ + uint32_t spage; /* start of page to load */ + uint32_t npage; /* normal world page data to copy */ + uint32_t page_idx; /* page index relative to start of this session */ + uint32_t page_bit; /* bit number page_idx set for rw data */ + void *hash_offset; /* hash of page data */ + uint32_t cpy_size = SMALL_PAGE_SIZE; + size_t hash_size; + uint32_t remain_data; + + /* Address has a session ? */ + TEE_ASSERT(ts != NULL); + + spage = va_addr & 0xFFFFF000; + smem = tee_mm_get_smem(ts->mm); + npage = (uint32_t) (ts->nmem) + spage - smem; + page_idx = ((spage - smem) >> SMALL_PAGE_SHIFT); + page_bit = 1 << page_idx; + if (tee_hash_get_digest_size(ts->head->hash_type, &hash_size) != + TEE_SUCCESS) { + EMSG("invalid hash type 0x%x", + (unsigned int)ts->head->hash_type); + TEE_ASSERT(0); + } + + remain_data = smem + ts->smem_size - spage; + /* + * Check that there's more than just ZI in this page as we don't have + * any hash for a pure ZI page. + */ + if (remain_data > ts->head->zi_size) { + if (remain_data - ts->head->zi_size < cpy_size) { + cpy_size = + smem + ts->smem_size - ts->head->zi_size - spage; + } + + /* copy memory */ + memcpy((void *)spage, (void *)npage, cpy_size); + + hash_offset = + (void *)(sizeof(ta_head_t) + + ts->head->nbr_func * sizeof(ta_func_head_t) + + hash_size * page_idx + (uint32_t) (ts->head)); + + /* check hash */ + if (tee_hash_check( + ts->head->hash_type, + hash_offset, hash_size, + (void *)spage, cpy_size) != TEE_SUCCESS) { + /* Hash did not match. */ + EMSG("PH 0x%x failed", (unsigned int)spage); + TEE_ASSERT(0); + } + } + + /* restore/update rw data */ + if (ts->head->ro_size < spage - smem + SMALL_PAGE_SIZE && + (ts->rw_data_usage & page_bit) != 0) { + uint32_t hi = MIN(ts->head->rw_size + + ts->head->zi_size + ts->head->ro_size, + spage - smem + SMALL_PAGE_SIZE); + + uint32_t lo = MAX(ts->head->ro_size, + (spage - smem)); + + memcpy((void *)(smem + lo), + (void *)(ts->rw_data + (lo - ts->head->ro_size)), + hi - lo); + } + + return (void *)ts; +} + +/*----------------------------------------------------------------------------- + * Checks if a page at va_addr contains rw data which should be saved + * Returns 1 if the page contains data, 0 otherwise + * + * Executed in abort mode + *---------------------------------------------------------------------------*/ +uint32_t tee_ta_check_rw(const uint32_t va_addr, const void *ctx_handle) +{ + struct tee_ta_ctx *ctx; + uint32_t smem; /* start memroy address for session */ + uint32_t spage; /* start address for page */ + + /* check if session is still valid */ + TAILQ_FOREACH(ctx, &tee_ctxes, link) { + if (ctx == ctx_handle) + break; + } + if (ctx != ctx_handle) { + /* session has been removed */ + /* XXX can this ever happen?? /EJENWIK 111219 */ + return 0; + } + + smem = tee_mm_get_smem(ctx->mm); + spage = va_addr & 0xFFFFF000; + + if (va_addr < smem || va_addr >= smem + ctx->smem_size) { + /* Out of bounds nothing to remove */ + return 0; + } + + /* check if we have ro data */ + if (ctx->head->ro_size < spage - smem + SMALL_PAGE_SIZE) + return 1; + + return 0; +} + +/*----------------------------------------------------------------------------- + * Saves rw data in a page at va_addr + * NOTE: No parameter checking! It is assumed that tee_ta_check_rw is called + * prior this function + * + * Executed in abort mode + *---------------------------------------------------------------------------*/ +void tee_ta_save_rw(const uint32_t va_addr, const void *ctx_handle) +{ + struct tee_ta_ctx *ctx = (struct tee_ta_ctx *)ctx_handle; + uint32_t smem; /* start memory address for session */ + uint32_t spage; /* start of page to save rw data from */ + uint32_t page_idx; /* page index relative to start of this session */ + uint32_t page_bit; /* bit number page_idx */ + uint32_t lo; /* start offset (from smem) for rw data to save */ + uint32_t hi; /* end offset (from smem) for rw data to save */ + + smem = tee_mm_get_smem(ctx->mm); + spage = va_addr & 0xFFFFF000; + page_idx = ((spage - smem) >> SMALL_PAGE_SHIFT); + page_bit = 1 << page_idx; + + lo = MAX(ctx->head->ro_size, (spage - smem)); + + hi = MIN(ctx->head->rw_size + ctx->head->zi_size + ctx->head->ro_size, + (spage - smem + SMALL_PAGE_SIZE)); + + memcpy((void *)(ctx->rw_data + lo - ctx->head->ro_size), + (void *)(smem + lo), hi - lo); + + /* update page usage */ + ctx->rw_data_usage |= page_bit; +} diff --git a/core/lib/libtomcrypt/include/tee_ltc_wrapper.h b/core/lib/libtomcrypt/include/tee_ltc_wrapper.h new file mode 100644 index 00000000000..2be3c04fe22 --- /dev/null +++ b/core/lib/libtomcrypt/include/tee_ltc_wrapper.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __TEE_LTC_WRAPPER_H_ +#define __TEE_LTC_WRAPPER_H_ + +#include +#include + +#define LTC_MAX_BITS_PER_VARIABLE (4096) + +void tee_ltc_init(void); +void tee_ltc_deinit(void); +TEE_Result tee_algo_to_ltc_hashindex(uint32_t algo, int *ltc_hashindex); +TEE_Result tee_algo_to_ltc_cipherindex(uint32_t algo, int *ltc_cipherindex); +int tee_ltc_get_rng_mpa(void); + +#endif /* __TEE_LTC_WRAPPER_H_ */ diff --git a/core/lib/libtomcrypt/include/tomcrypt.h b/core/lib/libtomcrypt/include/tomcrypt.h new file mode 100644 index 00000000000..3acadb03ac5 --- /dev/null +++ b/core/lib/libtomcrypt/include/tomcrypt.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TOMCRYPT_H_ +#define TOMCRYPT_H_ +#include +#include +#include +#include +#include +#include +#include + +/* use configuration data */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* version */ +#define CRYPT 0x0117 +#define SCRYPT "1.17" + +/* max size of either a cipher/hash block or symmetric key [largest of the two] */ +#define MAXBLOCKSIZE 128 + +/* descriptor table size */ +#define TAB_SIZE 32 + +/* error codes [will be expanded in future releases] */ +enum { + CRYPT_OK=0, /* Result OK */ + CRYPT_ERROR, /* Generic Error */ + CRYPT_NOP, /* Not a failure but no operation was performed */ + + CRYPT_INVALID_KEYSIZE, /* Invalid key size given */ + CRYPT_INVALID_ROUNDS, /* Invalid number of rounds */ + CRYPT_FAIL_TESTVECTOR, /* Algorithm failed test vectors */ + + CRYPT_BUFFER_OVERFLOW, /* Not enough space for output */ + CRYPT_INVALID_PACKET, /* Invalid input packet given */ + + CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */ + CRYPT_ERROR_READPRNG, /* Could not read enough from PRNG */ + + CRYPT_INVALID_CIPHER, /* Invalid cipher specified */ + CRYPT_INVALID_HASH, /* Invalid hash specified */ + CRYPT_INVALID_PRNG, /* Invalid PRNG specified */ + + CRYPT_MEM, /* Out of memory */ + + CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */ + CRYPT_PK_NOT_PRIVATE, /* Requires a private PK key */ + + CRYPT_INVALID_ARG, /* Generic invalid argument */ + CRYPT_FILE_NOTFOUND, /* File Not Found */ + + CRYPT_PK_INVALID_TYPE, /* Invalid type of PK key */ + CRYPT_PK_INVALID_SYSTEM,/* Invalid PK system specified */ + CRYPT_PK_DUP, /* Duplicate key already in key ring */ + CRYPT_PK_NOT_FOUND, /* Key not found in keyring */ + CRYPT_PK_INVALID_SIZE, /* Invalid size input for PK parameters */ + + CRYPT_INVALID_PRIME_SIZE,/* Invalid size of prime requested */ + CRYPT_PK_INVALID_PADDING /* Invalid padding on input */ +}; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus + } +#endif + +#endif /* TOMCRYPT_H_ */ + + +/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt.h,v $ */ +/* $Revision: 1.21 $ */ +/* $Date: 2006/12/16 19:34:05 $ */ diff --git a/core/lib/libtomcrypt/include/tomcrypt_argchk.h b/core/lib/libtomcrypt/include/tomcrypt_argchk.h new file mode 100644 index 00000000000..ff56c829805 --- /dev/null +++ b/core/lib/libtomcrypt/include/tomcrypt_argchk.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Defines the LTC_ARGCHK macro used within the library */ +/* ARGTYPE is defined in mycrypt_cfg.h */ +#if ARGTYPE == 0 + +#include + +/* this is the default LibTomCrypt macro */ +void crypt_argchk(const char *v, const char *s, int d); +#define LTC_ARGCHK(x) if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } +#define LTC_ARGCHKVD(x) LTC_ARGCHK(x) + +#elif ARGTYPE == 1 + +/* fatal type of error */ +#define LTC_ARGCHK(x) assert((x)) +#define LTC_ARGCHKVD(x) LTC_ARGCHK(x) + +#elif ARGTYPE == 2 + +#define LTC_ARGCHK(x) if (!(x)) { fprintf(stderr, "\nwarning: ARGCHK failed at %s:%d\n", __FILE__, __LINE__); } +#define LTC_ARGCHKVD(x) LTC_ARGCHK(x) + +#elif ARGTYPE == 3 + +#define LTC_ARGCHK(x) +#define LTC_ARGCHKVD(x) LTC_ARGCHK(x) + +#elif ARGTYPE == 4 + +#define LTC_ARGCHK(x) if (!(x)) return CRYPT_INVALID_ARG; +#define LTC_ARGCHKVD(x) if (!(x)) return; + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_argchk.h,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/08/27 20:50:21 $ */ diff --git a/core/lib/libtomcrypt/include/tomcrypt_cfg.h b/core/lib/libtomcrypt/include/tomcrypt_cfg.h new file mode 100644 index 00000000000..db3e354c34e --- /dev/null +++ b/core/lib/libtomcrypt/include/tomcrypt_cfg.h @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* This is the build config file. + * + * With this you can setup what to inlcude/exclude automatically during any build. Just comment + * out the line that #define's the word for the thing you want to remove. phew! + */ + +#ifndef TOMCRYPT_CFG_H +#define TOMCRYPT_CFG_H + +#if defined(_WIN32) || defined(_MSC_VER) +#define LTC_CALL __cdecl +#else +#ifndef LTC_CALL + #define LTC_CALL +#endif +#endif + +#ifndef LTC_EXPORT +#define LTC_EXPORT +#endif + +/* certain platforms use macros for these, making the prototypes broken */ +#ifndef LTC_NO_PROTOTYPES + +/* you can change how memory allocation works ... */ +LTC_EXPORT void * LTC_CALL XMALLOC(size_t n); +LTC_EXPORT void * LTC_CALL XREALLOC(void *p, size_t n); +LTC_EXPORT void * LTC_CALL XCALLOC(size_t n, size_t s); +LTC_EXPORT void LTC_CALL XFREE(void *p); + +LTC_EXPORT void LTC_CALL XQSORT(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)); + + +/* change the clock function too */ +LTC_EXPORT clock_t LTC_CALL XCLOCK(void); + +/* various other functions */ +LTC_EXPORT void * LTC_CALL XMEMCPY(void *dest, const void *src, size_t n); +LTC_EXPORT int LTC_CALL XMEMCMP(const void *s1, const void *s2, size_t n); +LTC_EXPORT void * LTC_CALL XMEMSET(void *s, int c, size_t n); + +LTC_EXPORT int LTC_CALL XSTRCMP(const char *s1, const char *s2); + +#endif + +/* + * with ARGTYPE==4, LTC_ARGCHK() returns an error when an argument is not correct + */ +#define ARGTYPE 4 + +/* type of argument checking, 0=default, 1=fatal and 2=error+continue, 3=nothing */ +#ifndef ARGTYPE + #define ARGTYPE 0 +#endif + +/* Controls endianess and size of registers. Leave uncommented to get platform neutral [slower] code + * + * Note: in order to use the optimized macros your platform must support unaligned 32 and 64 bit read/writes. + * The x86 platforms allow this but some others [ARM for instance] do not. On those platforms you **MUST** + * use the portable [slower] macros. + */ + +/* detect x86-32 machines somewhat */ +#if !defined(__STRICT_ANSI__) && (defined(INTEL_CC) || (defined(_MSC_VER) && defined(WIN32)) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__)))) + #define ENDIAN_LITTLE + #define ENDIAN_32BITWORD + #define LTC_FAST + #define LTC_FAST_TYPE unsigned long +#endif + +/* detects MIPS R5900 processors (PS2) */ +#if (defined(__R5900) || defined(R5900) || defined(__R5900__)) && (defined(_mips) || defined(__mips__) || defined(mips)) + #define ENDIAN_LITTLE + #define ENDIAN_64BITWORD +#endif + +/* detect amd64 */ +#if !defined(__STRICT_ANSI__) && defined(__x86_64__) + #define ENDIAN_LITTLE + #define ENDIAN_64BITWORD + #define LTC_FAST + #define LTC_FAST_TYPE unsigned long +#endif + +/* detect PPC32 */ +#if !defined(__STRICT_ANSI__) && defined(LTC_PPC32) + #define ENDIAN_BIG + #define ENDIAN_32BITWORD + #define LTC_FAST + #define LTC_FAST_TYPE unsigned long +#endif + +/* detect sparc and sparc64 */ +#if defined(__sparc__) + #define ENDIAN_BIG + #if defined(__arch64__) + #define ENDIAN_64BITWORD + #else + #define ENDIAN_32BITWORD + #endif +#endif + + +#ifdef LTC_NO_FAST + #ifdef LTC_FAST + #undef LTC_FAST + #endif +#endif + +/* No asm is a quick way to disable anything "not portable" */ +#ifdef LTC_NO_ASM + #undef ENDIAN_LITTLE + #undef ENDIAN_BIG + #undef ENDIAN_32BITWORD + #undef ENDIAN_64BITWORD + #undef LTC_FAST + #undef LTC_FAST_TYPE + #define LTC_NO_ROLC + #define LTC_NO_BSWAP +#endif + +/* #define ENDIAN_LITTLE */ +/* #define ENDIAN_BIG */ + +/* #define ENDIAN_32BITWORD */ +/* #define ENDIAN_64BITWORD */ + +#if (defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) && !(defined(ENDIAN_32BITWORD) || defined(ENDIAN_64BITWORD)) + #error You must specify a word size as well as endianess in tomcrypt_cfg.h +#endif + +#if !(defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) + #define ENDIAN_NEUTRAL +#endif + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_cfg.h,v $ */ +/* $Revision: 1.19 $ */ +/* $Date: 2006/12/04 02:19:48 $ */ diff --git a/core/lib/libtomcrypt/include/tomcrypt_cipher.h b/core/lib/libtomcrypt/include/tomcrypt_cipher.h new file mode 100644 index 00000000000..b4db092bde3 --- /dev/null +++ b/core/lib/libtomcrypt/include/tomcrypt_cipher.h @@ -0,0 +1,584 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* ---- SYMMETRIC KEY STUFF ----- + * + * We put each of the ciphers scheduled keys in their own structs then we put all of + * the key formats in one union. This makes the function prototypes easier to use. + */ + +#ifdef LTC_RIJNDAEL +struct rijndael_key { + ulong32 eK[60], dK[60]; + int Nr; +}; +#endif + + +#ifdef LTC_DES +struct des_key { + ulong32 ek[32], dk[32]; +}; + +struct des3_key { + ulong32 ek[3][32], dk[3][32]; +}; +#endif + + +typedef union Symmetric_key { + struct des_key des; + struct des3_key des3; + struct rijndael_key rijndael; + void *data; +} symmetric_key; + +#ifdef LTC_ECB_MODE +/** A block cipher ECB structure */ +typedef struct { + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen; + /** The scheduled key */ + symmetric_key key; +} symmetric_ECB; +#endif + +#ifdef LTC_CFB_MODE +/** A block cipher CFB structure */ +typedef struct { + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen, + /** The padding offset */ + padlen; + /** The current IV */ + unsigned char IV[MAXBLOCKSIZE], + /** The pad used to encrypt/decrypt */ + pad[MAXBLOCKSIZE]; + /** The scheduled key */ + symmetric_key key; +} symmetric_CFB; +#endif + +#ifdef LTC_OFB_MODE +/** A block cipher OFB structure */ +typedef struct { + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen, + /** The padding offset */ + padlen; + /** The current IV */ + unsigned char IV[MAXBLOCKSIZE]; + /** The scheduled key */ + symmetric_key key; +} symmetric_OFB; +#endif + +#ifdef LTC_CBC_MODE +/** A block cipher CBC structure */ +typedef struct { + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen; + /** The current IV */ + unsigned char IV[MAXBLOCKSIZE]; + /** The scheduled key */ + symmetric_key key; +} symmetric_CBC; +#endif + + +#ifdef LTC_CTR_MODE +/** A block cipher CTR structure */ +typedef struct { + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen, + /** The padding offset */ + padlen, + /** The mode (endianess) of the CTR, 0==little, 1==big */ + mode, + /** counter width */ + ctrlen; + + /** The counter */ + unsigned char ctr[MAXBLOCKSIZE], + /** The pad used to encrypt/decrypt */ + pad[MAXBLOCKSIZE]; + /** The scheduled key */ + symmetric_key key; +} symmetric_CTR; +#endif + + +#ifdef LTC_LRW_MODE +/** A LRW structure */ +typedef struct { + /** The index of the cipher chosen (must be a 128-bit block cipher) */ + int cipher; + + /** The current IV */ + unsigned char IV[16], + + /** the tweak key */ + tweak[16], + + /** The current pad, it's the product of the first 15 bytes against the tweak key */ + pad[16]; + + /** The scheduled symmetric key */ + symmetric_key key; + +#ifdef LRW_TABLES + /** The pre-computed multiplication table */ + unsigned char PC[16][256][16]; +#endif +} symmetric_LRW; +#endif + +#ifdef LTC_F8_MODE +/** A block cipher F8 structure */ +typedef struct { + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen, + /** The padding offset */ + padlen; + /** The current IV */ + unsigned char IV[MAXBLOCKSIZE], + MIV[MAXBLOCKSIZE]; + /** Current block count */ + ulong32 blockcnt; + /** The scheduled key */ + symmetric_key key; +} symmetric_F8; +#endif + + +/** cipher descriptor table, last entry has "name == NULL" to mark the end of table */ +extern struct ltc_cipher_descriptor { + /** name of cipher */ + const char *name; + /** internal ID */ + unsigned char ID; + /** min keysize (octets) */ + int min_key_length, + /** max keysize (octets) */ + max_key_length, + /** block size (octets) */ + block_length, + /** default number of rounds */ + default_rounds; + /** Setup the cipher + @param key The input symmetric key + @param keylen The length of the input key (octets) + @param num_rounds The requested number of rounds (0==default) + @param skey [out] The destination of the scheduled key + @return CRYPT_OK if successful + */ + int (*setup)(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); + /** Encrypt a block + @param pt The plaintext + @param ct [out] The ciphertext + @param skey The scheduled key + @return CRYPT_OK if successful + */ + int (*ecb_encrypt)(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); + /** Decrypt a block + @param ct The ciphertext + @param pt [out] The plaintext + @param skey The scheduled key + @return CRYPT_OK if successful + */ + int (*ecb_decrypt)(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); + /** Test the block cipher + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled + */ + int (*test)(void); + + /** Terminate the context + @param skey The scheduled key + */ + void (*done)(symmetric_key *skey); + + /** Determine a key size + @param keysize [in/out] The size of the key desired and the suggested size + @return CRYPT_OK if successful + */ + int (*keysize)(int *keysize); + +/** Accelerators **/ + /** Accelerated ECB encryption + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_ecb_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, symmetric_key *skey); + + /** Accelerated ECB decryption + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_ecb_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, symmetric_key *skey); + + /** Accelerated CBC encryption + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param IV The initial value (input/output) + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_cbc_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, symmetric_key *skey); + + /** Accelerated CBC decryption + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param IV The initial value (input/output) + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_cbc_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, symmetric_key *skey); + + /** Accelerated CTR encryption + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param IV The initial value (input/output) + @param mode little or big endian counter (mode=0 or mode=1) + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_ctr_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, int mode, symmetric_key *skey); + + /** Accelerated LRW + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param IV The initial value (input/output) + @param tweak The LRW tweak + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_lrw_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, symmetric_key *skey); + + /** Accelerated LRW + @param ct Ciphertext + @param pt Plaintext + @param blocks The number of complete blocks to process + @param IV The initial value (input/output) + @param tweak The LRW tweak + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_lrw_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, symmetric_key *skey); + + /** Accelerated CCM packet (one-shot) + @param key The secret key to use + @param keylen The length of the secret key (octets) + @param uskey A previously scheduled key [optional can be NULL] + @param nonce The session nonce [use once] + @param noncelen The length of the nonce + @param header The header for the session + @param headerlen The length of the header (octets) + @param pt [out] The plaintext + @param ptlen The length of the plaintext (octets) + @param ct [out] The ciphertext + @param tag [out] The destination tag + @param taglen [in/out] The max size and resulting size of the authentication tag + @param direction Encrypt or Decrypt direction (0 or 1) + @return CRYPT_OK if successful + */ + int (*accel_ccm_memory)( + const unsigned char *key, unsigned long keylen, + symmetric_key *uskey, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen, + int direction); + + /** Accelerated GCM packet (one shot) + @param key The secret key + @param keylen The length of the secret key + @param IV The initial vector + @param IVlen The length of the initial vector + @param adata The additional authentication data (header) + @param adatalen The length of the adata + @param pt The plaintext + @param ptlen The length of the plaintext (ciphertext length is the same) + @param ct The ciphertext + @param tag [out] The MAC tag + @param taglen [in/out] The MAC tag length + @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT) + @return CRYPT_OK on success + */ + int (*accel_gcm_memory)( + const unsigned char *key, unsigned long keylen, + const unsigned char *IV, unsigned long IVlen, + const unsigned char *adata, unsigned long adatalen, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen, + int direction); + + /** Accelerated one shot LTC_OMAC + @param key The secret key + @param keylen The key length (octets) + @param in The message + @param inlen Length of message (octets) + @param out [out] Destination for tag + @param outlen [in/out] Initial and final size of out + @return CRYPT_OK on success + */ + int (*omac_memory)( + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + + /** Accelerated one shot XCBC + @param key The secret key + @param keylen The key length (octets) + @param in The message + @param inlen Length of message (octets) + @param out [out] Destination for tag + @param outlen [in/out] Initial and final size of out + @return CRYPT_OK on success + */ + int (*xcbc_memory)( + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + + /** Accelerated one shot F9 + @param key The secret key + @param keylen The key length (octets) + @param in The message + @param inlen Length of message (octets) + @param out [out] Destination for tag + @param outlen [in/out] Initial and final size of out + @return CRYPT_OK on success + @remark Requires manual padding + */ + int (*f9_memory)( + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +} cipher_descriptor[]; + + +/* make aes an alias */ +#define aes_setup rijndael_setup +#define aes_ecb_encrypt rijndael_ecb_encrypt +#define aes_ecb_decrypt rijndael_ecb_decrypt +#define aes_test rijndael_test +#define aes_done rijndael_done +#define aes_keysize rijndael_keysize + +#define aes_enc_setup rijndael_enc_setup +#define aes_enc_ecb_encrypt rijndael_enc_ecb_encrypt +#define aes_enc_keysize rijndael_enc_keysize + +int rijndael_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int rijndael_test(void); +void rijndael_done(symmetric_key *skey); +int rijndael_keysize(int *keysize); +int rijndael_enc_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int rijndael_enc_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +void rijndael_enc_done(symmetric_key *skey); +int rijndael_enc_keysize(int *keysize); +extern const struct ltc_cipher_descriptor rijndael_desc, aes_desc; +extern const struct ltc_cipher_descriptor rijndael_enc_desc, aes_enc_desc; + + + + +int des_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int des_test(void); +void des_done(symmetric_key *skey); +int des_keysize(int *keysize); +int des3_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int des3_test(void); +void des3_done(symmetric_key *skey); +int des3_keysize(int *keysize); +extern const struct ltc_cipher_descriptor des_desc, des3_desc; + + +#ifdef LTC_ECB_MODE +int ecb_start(int cipher, const unsigned char *key, + int keylen, int num_rounds, symmetric_ECB *ecb); +int ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_ECB *ecb); +int ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_ECB *ecb); +int ecb_done(symmetric_ECB *ecb); +#endif + +#ifdef LTC_CFB_MODE +int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key, + int keylen, int num_rounds, symmetric_CFB *cfb); +int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb); +int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb); +int cfb_getiv(unsigned char *IV, unsigned long *len, symmetric_CFB *cfb); +int cfb_setiv(const unsigned char *IV, unsigned long len, symmetric_CFB *cfb); +int cfb_done(symmetric_CFB *cfb); +#endif + +#ifdef LTC_OFB_MODE +int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key, + int keylen, int num_rounds, symmetric_OFB *ofb); +int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_OFB *ofb); +int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb); +int ofb_getiv(unsigned char *IV, unsigned long *len, symmetric_OFB *ofb); +int ofb_setiv(const unsigned char *IV, unsigned long len, symmetric_OFB *ofb); +int ofb_done(symmetric_OFB *ofb); +#endif + +#ifdef LTC_CBC_MODE +int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key, + int keylen, int num_rounds, symmetric_CBC *cbc); +int cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CBC *cbc); +int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc); +int cbc_getiv(unsigned char *IV, unsigned long *len, symmetric_CBC *cbc); +int cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc); +int cbc_done(symmetric_CBC *cbc); +#endif + +#ifdef LTC_CTR_MODE + +#define CTR_COUNTER_LITTLE_ENDIAN 0x0000 +#define CTR_COUNTER_BIG_ENDIAN 0x1000 +#define LTC_CTR_RFC3686 0x2000 + +int ctr_start( int cipher, + const unsigned char *IV, + const unsigned char *key, int keylen, + int num_rounds, int ctr_mode, + symmetric_CTR *ctr); +int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr); +int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr); +int ctr_getiv(unsigned char *IV, unsigned long *len, symmetric_CTR *ctr); +int ctr_setiv(const unsigned char *IV, unsigned long len, symmetric_CTR *ctr); +int ctr_done(symmetric_CTR *ctr); +int ctr_test(void); +#endif + +#ifdef LTC_LRW_MODE + +#define LRW_ENCRYPT 0 +#define LRW_DECRYPT 1 + +int lrw_start( int cipher, + const unsigned char *IV, + const unsigned char *key, int keylen, + const unsigned char *tweak, + int num_rounds, + symmetric_LRW *lrw); +int lrw_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_LRW *lrw); +int lrw_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_LRW *lrw); +int lrw_getiv(unsigned char *IV, unsigned long *len, symmetric_LRW *lrw); +int lrw_setiv(const unsigned char *IV, unsigned long len, symmetric_LRW *lrw); +int lrw_done(symmetric_LRW *lrw); +int lrw_test(void); + +/* don't call */ +int lrw_process(const unsigned char *pt, unsigned char *ct, unsigned long len, int mode, symmetric_LRW *lrw); +#endif + +#ifdef LTC_F8_MODE +int f8_start( int cipher, const unsigned char *IV, + const unsigned char *key, int keylen, + const unsigned char *salt_key, int skeylen, + int num_rounds, symmetric_F8 *f8); +int f8_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_F8 *f8); +int f8_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_F8 *f8); +int f8_getiv(unsigned char *IV, unsigned long *len, symmetric_F8 *f8); +int f8_setiv(const unsigned char *IV, unsigned long len, symmetric_F8 *f8); +int f8_done(symmetric_F8 *f8); +int f8_test_mode(void); +#endif + +#ifdef LTC_XTS_MODE +typedef struct { + symmetric_key key1, key2; + int cipher; +} symmetric_xts; + +int xts_start( int cipher, + const unsigned char *key1, + const unsigned char *key2, + unsigned long keylen, + int num_rounds, + symmetric_xts *xts); + +int xts_encrypt( + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + const unsigned char *tweak, + symmetric_xts *xts); +int xts_decrypt( + const unsigned char *ct, unsigned long ptlen, + unsigned char *pt, + const unsigned char *tweak, + symmetric_xts *xts); + +void xts_done(symmetric_xts *xts); +int xts_test(void); +void xts_mult_x(unsigned char *I); +#endif + +int find_cipher(const char *name); +int find_cipher_any(const char *name, int blocklen, int keylen); +int find_cipher_id(unsigned char ID); +int register_cipher(const struct ltc_cipher_descriptor *cipher); +int unregister_cipher(const struct ltc_cipher_descriptor *cipher); +int cipher_is_valid(int idx); + +LTC_MUTEX_PROTO(ltc_cipher_mutex) + +/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_cipher.h,v $ */ +/* $Revision: 1.54 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/core/lib/libtomcrypt/include/tomcrypt_custom.h b/core/lib/libtomcrypt/include/tomcrypt_custom.h new file mode 100644 index 00000000000..a23e155fee4 --- /dev/null +++ b/core/lib/libtomcrypt/include/tomcrypt_custom.h @@ -0,0 +1,401 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * Copyright (c) 2014, STMicroelectronics International N.V. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TOMCRYPT_CUSTOM_H_ +#define TOMCRYPT_CUSTOM_H_ + +#define LTC_NO_PROTOTYPES +#define LTC_SOURCE +#define LTC_NO_TABLES +// #define LTC_VERBOSE + +/* macros for various libc functions you can change for embedded targets */ +#ifndef XMALLOC + #ifdef malloc + #define LTC_NO_PROTOTYPES + #endif +#define XMALLOC malloc +#endif +#ifndef XREALLOC + #ifdef realloc + #define LTC_NO_PROTOTYPES + #endif +#define XREALLOC realloc +#endif +#ifndef XCALLOC + #ifdef calloc + #define LTC_NO_PROTOTYPES + #endif +#define XCALLOC calloc +#endif +#ifndef XFREE + #ifdef free + #define LTC_NO_PROTOTYPES + #endif +#define XFREE free +#endif + +#ifndef XMEMSET + #ifdef memset + #define LTC_NO_PROTOTYPES + #endif +#define XMEMSET memset +#endif +#ifndef XMEMCPY + #ifdef memcpy + #define LTC_NO_PROTOTYPES + #endif +#define XMEMCPY memcpy +#endif +#ifndef XMEMCMP + #ifdef memcmp + #define LTC_NO_PROTOTYPES + #endif +#define XMEMCMP memcmp +#endif +#ifndef XSTRCMP + #ifdef strcmp + #define LTC_NO_PROTOTYPES + #endif +#define XSTRCMP strcmp +#endif + +#ifndef XCLOCK +#define XCLOCK clock +#endif +#ifndef XCLOCKS_PER_SEC +#define XCLOCKS_PER_SEC CLOCKS_PER_SEC +#endif + +#ifndef XQSORT + #ifdef qsort + #define LTC_NO_PROTOTYPES + #endif +#define XQSORT qsort +#endif + +/* Easy button? */ +#ifdef LTC_EASY + #define LTC_NO_CIPHERS + #define LTC_RIJNDAEL + #define LTC_BLOWFISH + #define LTC_DES + #define LTC_CAST5 + + #define LTC_NO_MODES + #define LTC_ECB_MODE + #define LTC_CBC_MODE + #define LTC_CTR_MODE + + #define LTC_NO_HASHES + #define LTC_SHA1 + #define LTC_SHA512 + #define LTC_SHA384 + #define LTC_SHA256 + #define LTC_SHA224 + + #define LTC_NO_MACS + #define LTC_HMAC + #define LTC_OMAC + #define LTC_CCM_MODE + + #define LTC_NO_PRNGS + #define LTC_SPRNG + #define LTC_YARROW + #define LTC_DEVRANDOM + #define TRY_URANDOM_FIRST + + #define LTC_NO_PK + #define LTC_MRSA + #define LTC_MECC +#endif + +/* Use small code where possible */ +/* #define LTC_SMALL_CODE */ + +/* Enable self-test test vector checking */ +#ifndef LTC_NO_TEST + #define LTC_TEST +#endif + +/* we want do not want any predefined PRNG */ +#define LTC_NO_PRNGS + +/* clean the stack of functions which put private information on stack */ +/* #define LTC_CLEAN_STACK */ + +/* disable all file related functions */ +#define LTC_NO_FILE + +/* disable all forms of ASM */ +#define LTC_NO_ASM */ + +/* disable FAST mode */ +/* #define LTC_NO_FAST */ + +/* disable BSWAP on x86 */ +/* #define LTC_NO_BSWAP */ + +/* ---> Symmetric Block Ciphers <--- */ + +#define LTC_RIJNDAEL + +/* LTC_DES includes EDE triple-LTC_DES */ +#define LTC_DES + + +/* ---> Block Cipher Modes of Operation <--- */ +#ifndef LTC_NO_MODES + +#define LTC_CFB_MODE +#define LTC_OFB_MODE +#define LTC_ECB_MODE +#define LTC_CBC_MODE +#define LTC_CTR_MODE + +/* F8 chaining mode */ +#define LTC_F8_MODE + +/* LRW mode */ +#define LTC_LRW_MODE +#ifndef LTC_NO_TABLES + /* like GCM mode this will enable 16 8x128 tables [64KB] that make + * seeking very fast. + */ + #define LRW_TABLES +#endif + +/* XTS mode */ +#define LTC_XTS_MODE + +#endif /* LTC_NO_MODES */ + +/* ---> One-Way Hash Functions <--- */ +#ifndef LTC_NO_HASHES + +#define LTC_SHA512 +#define LTC_SHA384 +#define LTC_SHA256 +#define LTC_SHA224 +#define LTC_SHA1 +#define LTC_MD5 + +#endif /* LTC_NO_HASHES */ + +/* ---> MAC functions <--- */ +#ifndef LTC_NO_MACS + +#define LTC_HMAC +#define LTC_OMAC +#define LTC_PMAC +#define LTC_XCBC + + +/* ---> Encrypt + Authenticate Modes <--- */ + +#define LTC_EAX_MODE +#if defined(LTC_EAX_MODE) && !(defined(LTC_CTR_MODE) && defined(LTC_OMAC)) + #error LTC_EAX_MODE requires CTR and LTC_OMAC mode +#endif + +#define LTC_OCB_MODE +#define LTC_CCM_MODE +#define LTC_GCM_MODE + +/* Use 64KiB tables */ +#ifndef LTC_NO_TABLES + #define LTC_GCM_TABLES +#endif + +/* USE SSE2? requires GCC works on x86_32 and x86_64*/ +#ifdef LTC_GCM_TABLES +/* #define LTC_GCM_TABLES_SSE2 */ +#endif + +#endif /* LTC_NO_MACS */ + +/* Various tidbits of modern neatoness */ +#define LTC_BASE64 + +/* --> Pseudo Random Number Generators <--- */ +#ifndef LTC_NO_PRNGS + +/* Yarrow */ +#define LTC_YARROW +/* which descriptor of AES to use? */ +/* 0 = rijndael_enc 1 = aes_enc, 2 = rijndael [full], 3 = aes [full] */ +#define LTC_YARROW_AES 3 + +#if defined(LTC_YARROW) && !defined(LTC_CTR_MODE) + #error LTC_YARROW requires LTC_CTR_MODE chaining mode to be defined! +#endif + +/* a PRNG that simply reads from an available system source */ +#define LTC_SPRNG + +/* the *nix style /dev/random device */ +#define LTC_DEVRANDOM +/* try /dev/urandom before trying /dev/random */ +#define TRY_URANDOM_FIRST + +#endif /* LTC_NO_PRNGS */ + +/* ---> Public Key Crypto <--- */ +#ifndef LTC_NO_PK + +/* Include RSA support */ +#define LTC_MRSA + +/* Include Diffie-Hellman support */ +/* + * From libtomcrypt.org: + * DH vanished because nobody used it and it was a pain to support + * DH support rewritten by ST + */ +#define LTC_MDH + +/* Include Katja (a Rabin variant like RSA) */ +/* #define MKAT */ + +/* Digital Signature Algorithm */ +#define LTC_MDSA + +/* ECC */ +#define LTC_MECC + +/* use Shamir's trick for point mul (speeds up signature verification) */ +#define LTC_ECC_SHAMIR + +#if defined(TFM_LTC_DESC) && defined(LTC_MECC) + #define LTC_MECC_ACCEL +#endif + +/* do we want fixed point ECC */ +/* #define LTC_MECC_FP */ + +/* Timing Resistant? */ +/* #define LTC_ECC_TIMING_RESISTANT */ + +#endif /* LTC_NO_PK */ + +/* LTC_PKCS #1 (RSA) and #5 (Password Handling) stuff */ +#ifndef LTC_NO_PKCS + +#define LTC_PKCS_1 +#define LTC_PKCS_5 + +/* Include ASN.1 DER (required by DSA/RSA) */ +#define LTC_DER + +#endif /* LTC_NO_PKCS */ + +/* cleanup */ + +#ifdef LTC_MECC +/* Supported ECC Key Sizes */ +#ifndef LTC_NO_CURVES + #define ECC192 + #define ECC224 + #define ECC256 + #define ECC384 + #define ECC521 +#endif +#endif + +#if defined(LTC_MECC) || defined(LTC_MRSA) || defined(LTC_MDSA) || defined(MKATJA) + /* Include the MPI functionality? (required by the PK algorithms) */ + #define MPI +#endif + +#ifdef LTC_MRSA + #define LTC_PKCS_1 +#endif + +#if defined(LTC_DER) && !defined(MPI) + #error ASN.1 DER requires MPI functionality +#endif + +#if (defined(LTC_MDSA) || defined(LTC_MRSA) || defined(LTC_MECC) || defined(MKATJA)) && !defined(LTC_DER) + #error PK requires ASN.1 DER functionality, make sure LTC_DER is enabled +#endif + +/* THREAD management */ +#ifdef LTC_PTHREAD + +#include + +#define LTC_MUTEX_GLOBAL(x) pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER; +#define LTC_MUTEX_PROTO(x) extern pthread_mutex_t x; +#define LTC_MUTEX_TYPE(x) pthread_mutex_t x; +#define LTC_MUTEX_INIT(x) pthread_mutex_init(x, NULL); +#define LTC_MUTEX_LOCK(x) pthread_mutex_lock(x); +#define LTC_MUTEX_UNLOCK(x) pthread_mutex_unlock(x); + +#else + +/* default no functions */ +#define LTC_MUTEX_GLOBAL(x) +#define LTC_MUTEX_PROTO(x) +#define LTC_MUTEX_TYPE(x) +#define LTC_MUTEX_INIT(x) +#define LTC_MUTEX_LOCK(x) +#define LTC_MUTEX_UNLOCK(x) + +#endif + +/* + * Here are a list of fixes required in libtomcrypt + */ + +#define LTC_LINARO_FIX_RSAWITHOUTCRT + +/* + * From libtomcrypt.org: + * DH vanished because nobody used it and it was a pain to support + * DH support was adapted from the master branch of libtomcrypt that can be + * found at + * http://dev.openaos.org/browser/trunk/buildroot/gen7/buildroot/package/libtomcrypt/libtomcrypt-dh.patch + * The original version was not taken as it makes use of static const array + * containing base and prime, and did not include subprime and x-bits + * constraints + */ +#define LTC_LINARO_FIX_DH + +/* Debuggers */ + +/* define this if you use Valgrind, note: it CHANGES the way SOBER-128 and LTC_RC4 work (see the code) */ +/* #define LTC_VALGRIND */ + +#endif + + + +/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_custom.h,v $ */ +/* $Revision: 1.73 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/core/lib/libtomcrypt/include/tomcrypt_hash.h b/core/lib/libtomcrypt/include/tomcrypt_hash.h new file mode 100644 index 00000000000..91d71abbae9 --- /dev/null +++ b/core/lib/libtomcrypt/include/tomcrypt_hash.h @@ -0,0 +1,406 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* ---- HASH FUNCTIONS ---- */ +#ifdef LTC_SHA512 +struct sha512_state { + ulong64 length, state[8]; + unsigned long curlen; + unsigned char buf[128]; +}; +#endif + +#ifdef LTC_SHA256 +struct sha256_state { + ulong64 length; + ulong32 state[8], curlen; + unsigned char buf[64]; +}; +#endif + +#ifdef LTC_SHA1 +struct sha1_state { + ulong64 length; + ulong32 state[5], curlen; + unsigned char buf[64]; +}; +#endif + +#ifdef LTC_MD5 +struct md5_state { + ulong64 length; + ulong32 state[4], curlen; + unsigned char buf[64]; +}; +#endif + +#ifdef LTC_MD4 +struct md4_state { + ulong64 length; + ulong32 state[4], curlen; + unsigned char buf[64]; +}; +#endif + +#ifdef LTC_TIGER +struct tiger_state { + ulong64 state[3], length; + unsigned long curlen; + unsigned char buf[64]; +}; +#endif + +#ifdef LTC_MD2 +struct md2_state { + unsigned char chksum[16], X[48], buf[16]; + unsigned long curlen; +}; +#endif + +#ifdef LTC_RIPEMD128 +struct rmd128_state { + ulong64 length; + unsigned char buf[64]; + ulong32 curlen, state[4]; +}; +#endif + +#ifdef LTC_RIPEMD160 +struct rmd160_state { + ulong64 length; + unsigned char buf[64]; + ulong32 curlen, state[5]; +}; +#endif + +#ifdef LTC_RIPEMD256 +struct rmd256_state { + ulong64 length; + unsigned char buf[64]; + ulong32 curlen, state[8]; +}; +#endif + +#ifdef LTC_RIPEMD320 +struct rmd320_state { + ulong64 length; + unsigned char buf[64]; + ulong32 curlen, state[10]; +}; +#endif + +#ifdef LTC_WHIRLPOOL +struct whirlpool_state { + ulong64 length, state[8]; + unsigned char buf[64]; + ulong32 curlen; +}; +#endif + +#ifdef LTC_CHC_HASH +struct chc_state { + ulong64 length; + unsigned char state[MAXBLOCKSIZE], buf[MAXBLOCKSIZE]; + ulong32 curlen; +}; +#endif + +typedef union Hash_state { + char dummy[1]; +#ifdef LTC_CHC_HASH + struct chc_state chc; +#endif +#ifdef LTC_WHIRLPOOL + struct whirlpool_state whirlpool; +#endif +#ifdef LTC_SHA512 + struct sha512_state sha512; +#endif +#ifdef LTC_SHA256 + struct sha256_state sha256; +#endif +#ifdef LTC_SHA1 + struct sha1_state sha1; +#endif +#ifdef LTC_MD5 + struct md5_state md5; +#endif +#ifdef LTC_MD4 + struct md4_state md4; +#endif +#ifdef LTC_MD2 + struct md2_state md2; +#endif +#ifdef LTC_TIGER + struct tiger_state tiger; +#endif +#ifdef LTC_RIPEMD128 + struct rmd128_state rmd128; +#endif +#ifdef LTC_RIPEMD160 + struct rmd160_state rmd160; +#endif +#ifdef LTC_RIPEMD256 + struct rmd256_state rmd256; +#endif +#ifdef LTC_RIPEMD320 + struct rmd320_state rmd320; +#endif + void *data; +} hash_state; + +/** hash descriptor */ +extern struct ltc_hash_descriptor { + /** name of hash */ + const char *name; + /** internal ID */ + unsigned char ID; + /** Size of digest in octets */ + unsigned long hashsize; + /** Input block size in octets */ + unsigned long blocksize; + /** ASN.1 OID */ + unsigned long OID[16]; + /** Length of DER encoding */ + unsigned long OIDlen; + + /** Init a hash state + @param hash The hash to initialize + @return CRYPT_OK if successful + */ + int (*init)(hash_state *hash); + /** Process a block of data + @param hash The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful + */ + int (*process)(hash_state *hash, const unsigned char *in, unsigned long inlen); + /** Produce the digest and store it + @param hash The hash state + @param out [out] The destination of the digest + @return CRYPT_OK if successful + */ + int (*done)(hash_state *hash, unsigned char *out); + /** Self-test + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled + */ + int (*test)(void); + + /* accelerated hmac callback: if you need to-do multiple packets just use the generic hmac_memory and provide a hash callback */ + int (*hmac_block)(const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +} hash_descriptor[]; + +#ifdef LTC_CHC_HASH +int chc_register(int cipher); +int chc_init(hash_state * md); +int chc_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int chc_done(hash_state * md, unsigned char *hash); +int chc_test(void); +extern const struct ltc_hash_descriptor chc_desc; +#endif + +#ifdef LTC_WHIRLPOOL +int whirlpool_init(hash_state * md); +int whirlpool_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int whirlpool_done(hash_state * md, unsigned char *hash); +int whirlpool_test(void); +extern const struct ltc_hash_descriptor whirlpool_desc; +#endif + +#ifdef LTC_SHA512 +int sha512_init(hash_state * md); +int sha512_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int sha512_done(hash_state * md, unsigned char *hash); +int sha512_test(void); +extern const struct ltc_hash_descriptor sha512_desc; +#endif + +#ifdef LTC_SHA384 +#ifndef LTC_SHA512 + #error LTC_SHA512 is required for LTC_SHA384 +#endif +int sha384_init(hash_state * md); +#define sha384_process sha512_process +int sha384_done(hash_state * md, unsigned char *hash); +int sha384_test(void); +extern const struct ltc_hash_descriptor sha384_desc; +#endif + +#ifdef LTC_SHA256 +int sha256_init(hash_state * md); +int sha256_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int sha256_done(hash_state * md, unsigned char *hash); +int sha256_test(void); +extern const struct ltc_hash_descriptor sha256_desc; + +#ifdef LTC_SHA224 +#ifndef LTC_SHA256 + #error LTC_SHA256 is required for LTC_SHA224 +#endif +int sha224_init(hash_state * md); +#define sha224_process sha256_process +int sha224_done(hash_state * md, unsigned char *hash); +int sha224_test(void); +extern const struct ltc_hash_descriptor sha224_desc; +#endif +#endif + +#ifdef LTC_SHA1 +int sha1_init(hash_state * md); +int sha1_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int sha1_done(hash_state * md, unsigned char *hash); +int sha1_test(void); +extern const struct ltc_hash_descriptor sha1_desc; +#endif + +#ifdef LTC_MD5 +int md5_init(hash_state * md); +int md5_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int md5_done(hash_state * md, unsigned char *hash); +int md5_test(void); +extern const struct ltc_hash_descriptor md5_desc; +#endif + +#ifdef LTC_MD4 +int md4_init(hash_state * md); +int md4_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int md4_done(hash_state * md, unsigned char *hash); +int md4_test(void); +extern const struct ltc_hash_descriptor md4_desc; +#endif + +#ifdef LTC_MD2 +int md2_init(hash_state * md); +int md2_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int md2_done(hash_state * md, unsigned char *hash); +int md2_test(void); +extern const struct ltc_hash_descriptor md2_desc; +#endif + +#ifdef LTC_TIGER +int tiger_init(hash_state * md); +int tiger_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int tiger_done(hash_state * md, unsigned char *hash); +int tiger_test(void); +extern const struct ltc_hash_descriptor tiger_desc; +#endif + +#ifdef LTC_RIPEMD128 +int rmd128_init(hash_state * md); +int rmd128_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int rmd128_done(hash_state * md, unsigned char *hash); +int rmd128_test(void); +extern const struct ltc_hash_descriptor rmd128_desc; +#endif + +#ifdef LTC_RIPEMD160 +int rmd160_init(hash_state * md); +int rmd160_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int rmd160_done(hash_state * md, unsigned char *hash); +int rmd160_test(void); +extern const struct ltc_hash_descriptor rmd160_desc; +#endif + +#ifdef LTC_RIPEMD256 +int rmd256_init(hash_state * md); +int rmd256_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int rmd256_done(hash_state * md, unsigned char *hash); +int rmd256_test(void); +extern const struct ltc_hash_descriptor rmd256_desc; +#endif + +#ifdef LTC_RIPEMD320 +int rmd320_init(hash_state * md); +int rmd320_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int rmd320_done(hash_state * md, unsigned char *hash); +int rmd320_test(void); +extern const struct ltc_hash_descriptor rmd320_desc; +#endif + + +int find_hash(const char *name); +int find_hash_id(unsigned char ID); +int find_hash_oid(const unsigned long *ID, unsigned long IDlen); +int find_hash_any(const char *name, int digestlen); +int register_hash(const struct ltc_hash_descriptor *hash); +int unregister_hash(const struct ltc_hash_descriptor *hash); +int hash_is_valid(int idx); + +LTC_MUTEX_PROTO(ltc_hash_mutex) + +int hash_memory(int hash, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...); +int hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outlen); +int hash_file(int hash, const char *fname, unsigned char *out, unsigned long *outlen); + +/* a simple macro for making hash "process" functions */ +#define HASH_PROCESS(func_name, compress_name, state_var, block_size) \ +int func_name (hash_state * md, const unsigned char *in, unsigned long inlen) \ +{ \ + unsigned long n; \ + int err; \ + LTC_ARGCHK(md != NULL); \ + LTC_ARGCHK(in != NULL); \ + if (md-> state_var .curlen > sizeof(md-> state_var .buf)) { \ + return CRYPT_INVALID_ARG; \ + } \ + while (inlen > 0) { \ + if (md-> state_var .curlen == 0 && inlen >= block_size) { \ + if ((err = compress_name (md, (unsigned char *)in)) != CRYPT_OK) { \ + return err; \ + } \ + md-> state_var .length += block_size * 8; \ + in += block_size; \ + inlen -= block_size; \ + } else { \ + n = MIN(inlen, (block_size - md-> state_var .curlen)); \ + memcpy(md-> state_var .buf + md-> state_var.curlen, in, (size_t)n); \ + md-> state_var .curlen += n; \ + in += n; \ + inlen -= n; \ + if (md-> state_var .curlen == block_size) { \ + if ((err = compress_name (md, md-> state_var .buf)) != CRYPT_OK) { \ + return err; \ + } \ + md-> state_var .length += 8*block_size; \ + md-> state_var .curlen = 0; \ + } \ + } \ + } \ + return CRYPT_OK; \ +} + +/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_hash.h,v $ */ +/* $Revision: 1.22 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/include/tomcrypt_mac.h b/core/lib/libtomcrypt/include/tomcrypt_mac.h new file mode 100644 index 00000000000..8b75fda95a3 --- /dev/null +++ b/core/lib/libtomcrypt/include/tomcrypt_mac.h @@ -0,0 +1,411 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef LTC_HMAC +typedef struct Hmac_state { + hash_state md; + int hash; + hash_state hashstate; + unsigned char *key; +} hmac_state; + +int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen); +int hmac_process(hmac_state *hmac, const unsigned char *in, unsigned long inlen); +int hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen); +int hmac_test(void); +int hmac_memory(int hash, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int hmac_memory_multi(int hash, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...); +int hmac_file(int hash, const char *fname, const unsigned char *key, + unsigned long keylen, + unsigned char *dst, unsigned long *dstlen); +#endif + +#ifdef LTC_OMAC + +typedef struct { + int cipher_idx, + buflen, + blklen; + unsigned char block[MAXBLOCKSIZE], + prev[MAXBLOCKSIZE], + Lu[2][MAXBLOCKSIZE]; + symmetric_key key; +} omac_state; + +int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen); +int omac_process(omac_state *omac, const unsigned char *in, unsigned long inlen); +int omac_done(omac_state *omac, unsigned char *out, unsigned long *outlen); +int omac_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int omac_memory_multi(int cipher, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...); +int omac_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *filename, + unsigned char *out, unsigned long *outlen); +int omac_test(void); +#endif /* LTC_OMAC */ + +#ifdef LTC_PMAC + +typedef struct { + unsigned char Ls[32][MAXBLOCKSIZE], /* L shifted by i bits to the left */ + Li[MAXBLOCKSIZE], /* value of Li [current value, we calc from previous recall] */ + Lr[MAXBLOCKSIZE], /* L * x^-1 */ + block[MAXBLOCKSIZE], /* currently accumulated block */ + checksum[MAXBLOCKSIZE]; /* current checksum */ + + symmetric_key key; /* scheduled key for cipher */ + unsigned long block_index; /* index # for current block */ + int cipher_idx, /* cipher idx */ + block_len, /* length of block */ + buflen; /* number of bytes in the buffer */ +} pmac_state; + +int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen); +int pmac_process(pmac_state *pmac, const unsigned char *in, unsigned long inlen); +int pmac_done(pmac_state *pmac, unsigned char *out, unsigned long *outlen); + +int pmac_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *msg, unsigned long msglen, + unsigned char *out, unsigned long *outlen); + +int pmac_memory_multi(int cipher, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...); + +int pmac_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *filename, + unsigned char *out, unsigned long *outlen); + +int pmac_test(void); + +/* internal functions */ +int pmac_ntz(unsigned long x); +void pmac_shift_xor(pmac_state *pmac); + +#endif /* PMAC */ + +#ifdef LTC_EAX_MODE + +#if !(defined(LTC_OMAC) && defined(LTC_CTR_MODE)) + #error LTC_EAX_MODE requires LTC_OMAC and CTR +#endif + +typedef struct { + unsigned char N[MAXBLOCKSIZE]; + symmetric_CTR ctr; + omac_state headeromac, ctomac; +} eax_state; + +int eax_init(eax_state *eax, int cipher, const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen); + +int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, unsigned long length); +int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, unsigned long length); +int eax_addheader(eax_state *eax, const unsigned char *header, unsigned long length); +int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen); + +int eax_encrypt_authenticate_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen, + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen); + +int eax_decrypt_verify_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + unsigned char *tag, unsigned long taglen, + int *stat); + + int eax_test(void); +#endif /* EAX MODE */ + +#ifdef LTC_OCB_MODE +typedef struct { + unsigned char L[MAXBLOCKSIZE], /* L value */ + Ls[32][MAXBLOCKSIZE], /* L shifted by i bits to the left */ + Li[MAXBLOCKSIZE], /* value of Li [current value, we calc from previous recall] */ + Lr[MAXBLOCKSIZE], /* L * x^-1 */ + R[MAXBLOCKSIZE], /* R value */ + checksum[MAXBLOCKSIZE]; /* current checksum */ + + symmetric_key key; /* scheduled key for cipher */ + unsigned long block_index; /* index # for current block */ + int cipher, /* cipher idx */ + block_len; /* length of block */ +} ocb_state; + +int ocb_init(ocb_state *ocb, int cipher, + const unsigned char *key, unsigned long keylen, const unsigned char *nonce); + +int ocb_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned char *ct); +int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt); + +int ocb_done_encrypt(ocb_state *ocb, + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen); + +int ocb_done_decrypt(ocb_state *ocb, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + const unsigned char *tag, unsigned long taglen, int *stat); + +int ocb_encrypt_authenticate_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen); + +int ocb_decrypt_verify_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + const unsigned char *tag, unsigned long taglen, + int *stat); + +int ocb_test(void); + +/* internal functions */ +void ocb_shift_xor(ocb_state *ocb, unsigned char *Z); +int ocb_ntz(unsigned long x); +int s_ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, unsigned char *tag, unsigned long *taglen, int mode); + +#endif /* LTC_OCB_MODE */ + +#ifdef LTC_CCM_MODE + +#define CCM_ENCRYPT 0 +#define CCM_DECRYPT 1 + +int ccm_memory(int cipher, + const unsigned char *key, unsigned long keylen, + symmetric_key *uskey, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen, + int direction); + +int ccm_test(void); + +#endif /* LTC_CCM_MODE */ + +#if defined(LRW_MODE) || defined(LTC_GCM_MODE) +void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c); +#endif + + +/* table shared between GCM and LRW */ +#if defined(LTC_GCM_TABLES) || defined(LRW_TABLES) || ((defined(LTC_GCM_MODE) || defined(LTC_GCM_MODE)) && defined(LTC_FAST)) +extern const unsigned char gcm_shift_table[]; +#endif + +#ifdef LTC_GCM_MODE + +#define GCM_ENCRYPT 0 +#define GCM_DECRYPT 1 + +#define LTC_GCM_MODE_IV 0 +#define LTC_GCM_MODE_AAD 1 +#define LTC_GCM_MODE_TEXT 2 + +typedef struct { + symmetric_key K; + unsigned char H[16], /* multiplier */ + X[16], /* accumulator */ + Y[16], /* counter */ + Y_0[16], /* initial counter */ + buf[16]; /* buffer for stuff */ + + int cipher, /* which cipher */ + ivmode, /* Which mode is the IV in? */ + mode, /* mode the GCM code is in */ + buflen; /* length of data in buf */ + + ulong64 totlen, /* 64-bit counter used for IV and AAD */ + pttotlen; /* 64-bit counter for the PT */ + +#ifdef LTC_GCM_TABLES + unsigned char PC[16][256][16] /* 16 tables of 8x128 */ +#ifdef LTC_GCM_TABLES_SSE2 +__attribute__ ((aligned (16))) +#endif +; +#endif +} gcm_state; + +void gcm_mult_h(gcm_state *gcm, unsigned char *I); + +int gcm_init(gcm_state *gcm, int cipher, + const unsigned char *key, int keylen); + +int gcm_reset(gcm_state *gcm); + +int gcm_add_iv(gcm_state *gcm, + const unsigned char *IV, unsigned long IVlen); + +int gcm_add_aad(gcm_state *gcm, + const unsigned char *adata, unsigned long adatalen); + +int gcm_process(gcm_state *gcm, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + int direction); + +int gcm_done(gcm_state *gcm, + unsigned char *tag, unsigned long *taglen); + +int gcm_memory( int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *IV, unsigned long IVlen, + const unsigned char *adata, unsigned long adatalen, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen, + int direction); +int gcm_test(void); + +#endif /* LTC_GCM_MODE */ + +#ifdef LTC_PELICAN + +typedef struct pelican_state +{ + symmetric_key K; + unsigned char state[16]; + int buflen; +} pelican_state; + +int pelican_init(pelican_state *pelmac, const unsigned char *key, unsigned long keylen); +int pelican_process(pelican_state *pelmac, const unsigned char *in, unsigned long inlen); +int pelican_done(pelican_state *pelmac, unsigned char *out); +int pelican_test(void); + +int pelican_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out); + +#endif + +#ifdef LTC_XCBC + +/* add this to "keylen" to xcbc_init to use a pure three-key XCBC MAC */ +#define LTC_XCBC_PURE 0x8000UL + +typedef struct { + unsigned char K[3][MAXBLOCKSIZE], + IV[MAXBLOCKSIZE]; + + symmetric_key key; + + int cipher, + buflen, + blocksize; +} xcbc_state; + +int xcbc_init(xcbc_state *xcbc, int cipher, const unsigned char *key, unsigned long keylen); +int xcbc_process(xcbc_state *xcbc, const unsigned char *in, unsigned long inlen); +int xcbc_done(xcbc_state *xcbc, unsigned char *out, unsigned long *outlen); +int xcbc_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int xcbc_memory_multi(int cipher, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...); +int xcbc_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *filename, + unsigned char *out, unsigned long *outlen); +int xcbc_test(void); + +#endif + +#ifdef LTC_F9_MODE + +typedef struct { + unsigned char akey[MAXBLOCKSIZE], + ACC[MAXBLOCKSIZE], + IV[MAXBLOCKSIZE]; + + symmetric_key key; + + int cipher, + buflen, + keylen, + blocksize; +} f9_state; + +int f9_init(f9_state *f9, int cipher, const unsigned char *key, unsigned long keylen); +int f9_process(f9_state *f9, const unsigned char *in, unsigned long inlen); +int f9_done(f9_state *f9, unsigned char *out, unsigned long *outlen); +int f9_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int f9_memory_multi(int cipher, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...); +int f9_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *filename, + unsigned char *out, unsigned long *outlen); +int f9_test(void); + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_mac.h,v $ */ +/* $Revision: 1.23 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/core/lib/libtomcrypt/include/tomcrypt_macros.h b/core/lib/libtomcrypt/include/tomcrypt_macros.h new file mode 100644 index 00000000000..00468a84483 --- /dev/null +++ b/core/lib/libtomcrypt/include/tomcrypt_macros.h @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TOMCRYPT_MACROS_H_ +#define TOMCRYPT_MACROS_H_ + +/* fix for MSVC ...evil! */ +#ifdef _MSC_VER + #define CONST64(n) n ## ui64 + typedef unsigned __int64 ulong64; +#else + #define CONST64(n) n ## ULL + typedef unsigned long long ulong64; +#endif + +/* this is the "32-bit at least" data type + * Re-define it to suit your platform but it must be at least 32-bits + */ +#if defined(__x86_64__) || (defined(__sparc__) && defined(__arch64__)) + typedef unsigned ulong32; +#else + typedef unsigned long ulong32; +#endif + +/* ---- HELPER MACROS ---- */ +#ifdef ENDIAN_NEUTRAL + +#define STORE32L(x, y) \ + { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ + (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } + +#define LOAD32L(x, y) \ + { x = ((unsigned long)((y)[3] & 255)<<24) | \ + ((unsigned long)((y)[2] & 255)<<16) | \ + ((unsigned long)((y)[1] & 255)<<8) | \ + ((unsigned long)((y)[0] & 255)); } + +#define STORE64L(x, y) \ + { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ + (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ + (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ + (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } + +#define LOAD64L(x, y) \ + { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \ + (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \ + (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \ + (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } + +#define STORE32H(x, y) \ + { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ + (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } + +#define LOAD32H(x, y) \ + { x = ((unsigned long)((y)[0] & 255)<<24) | \ + ((unsigned long)((y)[1] & 255)<<16) | \ + ((unsigned long)((y)[2] & 255)<<8) | \ + ((unsigned long)((y)[3] & 255)); } + +#define STORE64H(x, y) \ + { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ + (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ + (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ + (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } + +#define LOAD64H(x, y) \ + { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \ + (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \ + (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \ + (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); } + +#endif /* ENDIAN_NEUTRAL */ + +#ifdef ENDIAN_LITTLE + +#if !defined(LTC_NO_BSWAP) && (defined(INTEL_CC) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__) || defined(__x86_64__)))) + +#define STORE32H(x, y) \ +asm __volatile__ ( \ + "bswapl %0 \n\t" \ + "movl %0,(%1)\n\t" \ + "bswapl %0 \n\t" \ + ::"r"(x), "r"(y)); + +#define LOAD32H(x, y) \ +asm __volatile__ ( \ + "movl (%1),%0\n\t" \ + "bswapl %0\n\t" \ + :"=r"(x): "r"(y)); + +#else + +#define STORE32H(x, y) \ + { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ + (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } + +#define LOAD32H(x, y) \ + { x = ((unsigned long)((y)[0] & 255)<<24) | \ + ((unsigned long)((y)[1] & 255)<<16) | \ + ((unsigned long)((y)[2] & 255)<<8) | \ + ((unsigned long)((y)[3] & 255)); } + +#endif + + +/* x86_64 processor */ +#if !defined(LTC_NO_BSWAP) && (defined(__GNUC__) && defined(__x86_64__)) + +#define STORE64H(x, y) \ +asm __volatile__ ( \ + "bswapq %0 \n\t" \ + "movq %0,(%1)\n\t" \ + "bswapq %0 \n\t" \ + ::"r"(x), "r"(y)); + +#define LOAD64H(x, y) \ +asm __volatile__ ( \ + "movq (%1),%0\n\t" \ + "bswapq %0\n\t" \ + :"=r"(x): "r"(y)); + +#else + +#define STORE64H(x, y) \ + { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ + (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ + (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ + (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } + +#define LOAD64H(x, y) \ + { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \ + (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \ + (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \ + (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); } + +#endif + +#ifdef ENDIAN_32BITWORD + +#define STORE32L(x, y) \ + { ulong32 __t = (x); XMEMCPY(y, &__t, 4); } + +#define LOAD32L(x, y) \ + XMEMCPY(&(x), y, 4); + +#define STORE64L(x, y) \ + { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ + (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ + (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ + (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } + +#define LOAD64L(x, y) \ + { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \ + (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \ + (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \ + (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } + +#else /* 64-bit words then */ + +#define STORE32L(x, y) \ + { ulong32 __t = (x); XMEMCPY(y, &__t, 4); } + +#define LOAD32L(x, y) \ + { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; } + +#define STORE64L(x, y) \ + { ulong64 __t = (x); XMEMCPY(y, &__t, 8); } + +#define LOAD64L(x, y) \ + { XMEMCPY(&(x), y, 8); } + +#endif /* ENDIAN_64BITWORD */ + +#endif /* ENDIAN_LITTLE */ + +#ifdef ENDIAN_BIG +#define STORE32L(x, y) \ + { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ + (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } + +#define LOAD32L(x, y) \ + { x = ((unsigned long)((y)[3] & 255)<<24) | \ + ((unsigned long)((y)[2] & 255)<<16) | \ + ((unsigned long)((y)[1] & 255)<<8) | \ + ((unsigned long)((y)[0] & 255)); } + +#define STORE64L(x, y) \ + { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ + (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ + (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ + (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } + +#define LOAD64L(x, y) \ + { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48) | \ + (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32) | \ + (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16) | \ + (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } + +#ifdef ENDIAN_32BITWORD + +#define STORE32H(x, y) \ + { ulong32 __t = (x); XMEMCPY(y, &__t, 4); } + +#define LOAD32H(x, y) \ + XMEMCPY(&(x), y, 4); + +#define STORE64H(x, y) \ + { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ + (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ + (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ + (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } + +#define LOAD64H(x, y) \ + { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48)| \ + (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32)| \ + (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16)| \ + (((ulong64)((y)[6] & 255))<<8)| (((ulong64)((y)[7] & 255))); } + +#else /* 64-bit words then */ + +#define STORE32H(x, y) \ + { ulong32 __t = (x); XMEMCPY(y, &__t, 4); } + +#define LOAD32H(x, y) \ + { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; } + +#define STORE64H(x, y) \ + { ulong64 __t = (x); XMEMCPY(y, &__t, 8); } + +#define LOAD64H(x, y) \ + { XMEMCPY(&(x), y, 8); } + +#endif /* ENDIAN_64BITWORD */ +#endif /* ENDIAN_BIG */ + +#define BSWAP(x) ( ((x>>24)&0x000000FFUL) | ((x<<24)&0xFF000000UL) | \ + ((x>>8)&0x0000FF00UL) | ((x<<8)&0x00FF0000UL) ) + + +/* 32-bit Rotates */ +#if defined(_MSC_VER) + +/* instrinsic rotate */ +#include +#pragma intrinsic(_lrotr,_lrotl) +#define ROR(x,n) _lrotr(x,n) +#define ROL(x,n) _lrotl(x,n) +#define RORc(x,n) _lrotr(x,n) +#define ROLc(x,n) _lrotl(x,n) + +#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(INTEL_CC) && !defined(LTC_NO_ASM) + +static inline unsigned ROL(unsigned word, int i) +{ + asm ("roll %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +static inline unsigned ROR(unsigned word, int i) +{ + asm ("rorl %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +#ifndef LTC_NO_ROLC + +static inline unsigned ROLc(unsigned word, const int i) +{ + asm ("roll %2,%0" + :"=r" (word) + :"0" (word),"I" (i)); + return word; +} + +static inline unsigned RORc(unsigned word, const int i) +{ + asm ("rorl %2,%0" + :"=r" (word) + :"0" (word),"I" (i)); + return word; +} + +#else + +#define ROLc ROL +#define RORc ROR + +#endif + +#elif !defined(__STRICT_ANSI__) && defined(LTC_PPC32) + +static inline unsigned ROL(unsigned word, int i) +{ + asm ("rotlw %0,%0,%2" + :"=r" (word) + :"0" (word),"r" (i)); + return word; +} + +static inline unsigned ROR(unsigned word, int i) +{ + asm ("rotlw %0,%0,%2" + :"=r" (word) + :"0" (word),"r" (32-i)); + return word; +} + +#ifndef LTC_NO_ROLC + +static inline unsigned ROLc(unsigned word, const int i) +{ + asm ("rotlwi %0,%0,%2" + :"=r" (word) + :"0" (word),"I" (i)); + return word; +} + +static inline unsigned RORc(unsigned word, const int i) +{ + asm ("rotrwi %0,%0,%2" + :"=r" (word) + :"0" (word),"I" (i)); + return word; +} + +#else + +#define ROLc ROL +#define RORc ROR + +#endif + + +#else + +/* rotates the hard way */ +#define ROL(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) +#define ROR(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) +#define ROLc(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) +#define RORc(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) + +#endif + + +/* 64-bit Rotates */ +#if !defined(__STRICT_ANSI__) && defined(__GNUC__) && defined(__x86_64__) && !defined(LTC_NO_ASM) + +static inline unsigned long ROL64(unsigned long word, int i) +{ + asm("rolq %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +static inline unsigned long ROR64(unsigned long word, int i) +{ + asm("rorq %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +#ifndef LTC_NO_ROLC + +static inline unsigned long ROL64c(unsigned long word, const int i) +{ + asm("rolq %2,%0" + :"=r" (word) + :"0" (word),"J" (i)); + return word; +} + +static inline unsigned long ROR64c(unsigned long word, const int i) +{ + asm("rorq %2,%0" + :"=r" (word) + :"0" (word),"J" (i)); + return word; +} + +#else /* LTC_NO_ROLC */ + +#define ROL64c ROL64 +#define ROR64c ROR64 + +#endif + +#else /* Not x86_64 */ + +#define ROL64(x, y) \ + ( (((x)<<((ulong64)(y)&63)) | \ + (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF)) + +#define ROR64(x, y) \ + ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \ + ((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF)) + +#define ROL64c(x, y) \ + ( (((x)<<((ulong64)(y)&63)) | \ + (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF)) + +#define ROR64c(x, y) \ + ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \ + ((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF)) + +#endif + +#ifndef MAX + #define MAX(x, y) ( ((x)>(y))?(x):(y) ) +#endif + +#ifndef MIN + #define MIN(x, y) ( ((x)<(y))?(x):(y) ) +#endif + +/* extract a byte portably */ +#ifdef _MSC_VER + #define byte(x, n) ((unsigned char)((x) >> (8 * (n)))) +#else + #define byte(x, n) (((x) >> (8 * (n))) & 255) +#endif + + +#endif /* TOMCRYPT_MACROS_H_ */ +/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_macros.h,v $ */ +/* $Revision: 1.15 $ */ +/* $Date: 2006/11/29 23:43:57 $ */ diff --git a/core/lib/libtomcrypt/include/tomcrypt_math.h b/core/lib/libtomcrypt/include/tomcrypt_math.h new file mode 100644 index 00000000000..f45d00d5864 --- /dev/null +++ b/core/lib/libtomcrypt/include/tomcrypt_math.h @@ -0,0 +1,536 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** math functions **/ + +#define LTC_MP_LT -1 +#define LTC_MP_EQ 0 +#define LTC_MP_GT 1 + +#define LTC_MP_NO 0 +#define LTC_MP_YES 1 + +#ifndef LTC_MECC + typedef void ecc_point; +#endif + +#ifndef LTC_MRSA + typedef void rsa_key; +#endif + +/** math descriptor */ +typedef struct { + /** Name of the math provider */ + const char *name; + + /** Bits per digit, amount of bits must fit in an unsigned long */ + int bits_per_digit; + +/* ---- init/deinit functions ---- */ + + /** initialize a bignum + @param a The number to initialize + @return CRYPT_OK on success + */ + int (*init)(void **a); + + /** init copy + @param dst The number to initialize and write to + @param src The number to copy from + @return CRYPT_OK on success + */ + int (*init_copy)(void **dst, void *src); + + /** deinit + @param a The number to free + @return CRYPT_OK on success + */ + void (*deinit)(void *a); + +/* ---- data movement ---- */ + + /** negate + @param src The number to negate + @param dst The destination + @return CRYPT_OK on success + */ + int (*neg)(void *src, void *dst); + + /** copy + @param src The number to copy from + @param dst The number to write to + @return CRYPT_OK on success + */ + int (*copy)(void *src, void *dst); + +/* ---- trivial low level functions ---- */ + + /** set small constant + @param a Number to write to + @param n Source upto bits_per_digit (actually meant for very small constants) + @return CRYPT_OK on succcess + */ + int (*set_int)(void *a, unsigned long n); + + /** get small constant + @param a Number to read, only fetches upto bits_per_digit from the number + @return The lower bits_per_digit of the integer (unsigned) + */ + unsigned long (*get_int)(void *a); + + /** get digit n + @param a The number to read from + @param n The number of the digit to fetch + @return The bits_per_digit sized n'th digit of a + */ + unsigned long (*get_digit)(void *a, int n); + + /** Get the number of digits that represent the number + @param a The number to count + @return The number of digits used to represent the number + */ + int (*get_digit_count)(void *a); + + /** compare two integers + @param a The left side integer + @param b The right side integer + @return LTC_MP_LT if a < b, LTC_MP_GT if a > b and LTC_MP_EQ otherwise. (signed comparison) + */ + int (*compare)(void *a, void *b); + + /** compare against int + @param a The left side integer + @param b The right side integer (upto bits_per_digit) + @return LTC_MP_LT if a < b, LTC_MP_GT if a > b and LTC_MP_EQ otherwise. (signed comparison) + */ + int (*compare_d)(void *a, unsigned long n); + + /** Count the number of bits used to represent the integer + @param a The integer to count + @return The number of bits required to represent the integer + */ + int (*count_bits)(void * a); + + /** Count the number of LSB bits which are zero + @param a The integer to count + @return The number of contiguous zero LSB bits + */ + int (*count_lsb_bits)(void *a); + + /** Compute a power of two + @param a The integer to store the power in + @param n The power of two you want to store (a = 2^n) + @return CRYPT_OK on success + */ + int (*twoexpt)(void *a , int n); + +/* ---- radix conversions ---- */ + + /** read ascii string + @param a The integer to store into + @param str The string to read + @param radix The radix the integer has been represented in (2-64) + @return CRYPT_OK on success + */ + int (*read_radix)(void *a, const char *str, int radix); + + /** write number to string + @param a The integer to store + @param str The destination for the string + @param radix The radix the integer is to be represented in (2-64) + @return CRYPT_OK on success + */ + int (*write_radix)(void *a, char *str, int radix); + + /** get size as unsigned char string + @param a The integer to get the size (when stored in array of octets) + @return The length of the integer + */ + unsigned long (*unsigned_size)(void *a); + + /** store an integer as an array of octets + @param src The integer to store + @param dst The buffer to store the integer in + @return CRYPT_OK on success + */ + int (*unsigned_write)(void *src, unsigned char *dst); + + /** read an array of octets and store as integer + @param dst The integer to load + @param src The array of octets + @param len The number of octets + @return CRYPT_OK on success + */ + int (*unsigned_read)(void *dst, unsigned char *src, unsigned long len); + +/* ---- basic math ---- */ + + /** add two integers + @param a The first source integer + @param b The second source integer + @param c The destination of "a + b" + @return CRYPT_OK on success + */ + int (*add)(void *a, void *b, void *c); + + + /** add two integers + @param a The first source integer + @param b The second source integer (single digit of upto bits_per_digit in length) + @param c The destination of "a + b" + @return CRYPT_OK on success + */ + int (*addi)(void *a, unsigned long b, void *c); + + /** subtract two integers + @param a The first source integer + @param b The second source integer + @param c The destination of "a - b" + @return CRYPT_OK on success + */ + int (*sub)(void *a, void *b, void *c); + + /** subtract two integers + @param a The first source integer + @param b The second source integer (single digit of upto bits_per_digit in length) + @param c The destination of "a - b" + @return CRYPT_OK on success + */ + int (*subi)(void *a, unsigned long b, void *c); + + /** multiply two integers + @param a The first source integer + @param b The second source integer (single digit of upto bits_per_digit in length) + @param c The destination of "a * b" + @return CRYPT_OK on success + */ + int (*mul)(void *a, void *b, void *c); + + /** multiply two integers + @param a The first source integer + @param b The second source integer (single digit of upto bits_per_digit in length) + @param c The destination of "a * b" + @return CRYPT_OK on success + */ + int (*muli)(void *a, unsigned long b, void *c); + + /** Square an integer + @param a The integer to square + @param b The destination + @return CRYPT_OK on success + */ + int (*sqr)(void *a, void *b); + + /** Divide an integer + @param a The dividend + @param b The divisor + @param c The quotient (can be NULL to signify don't care) + @param d The remainder (can be NULL to signify don't care) + @return CRYPT_OK on success + */ + int (*mpdiv)(void *a, void *b, void *c, void *d); + + /** divide by two + @param a The integer to divide (shift right) + @param b The destination + @return CRYPT_OK on success + */ + int (*div_2)(void *a, void *b); + + /** Get remainder (small value) + @param a The integer to reduce + @param b The modulus (upto bits_per_digit in length) + @param c The destination for the residue + @return CRYPT_OK on success + */ + int (*modi)(void *a, unsigned long b, unsigned long *c); + + /** gcd + @param a The first integer + @param b The second integer + @param c The destination for (a, b) + @return CRYPT_OK on success + */ + int (*gcd)(void *a, void *b, void *c); + + /** lcm + @param a The first integer + @param b The second integer + @param c The destination for [a, b] + @return CRYPT_OK on success + */ + int (*lcm)(void *a, void *b, void *c); + + /** Modular reduction + @param a The source + @param b The modulus + @param c The destination (c = a mod b) + @return CRYPT_OK on success + */ + int (*mod)(void *a, void *b, void *c); + + + /** Modular multiplication + @param a The first source + @param b The second source + @param c The modulus + @param d The destination (a*b mod c) + @return CRYPT_OK on success + */ + int (*mulmod)(void *a, void *b, void *c, void *d); + + /** Modular squaring + @param a The first source + @param b The modulus + @param c The destination (a*a mod b) + @return CRYPT_OK on success + */ + int (*sqrmod)(void *a, void *b, void *c); + + /** Modular inversion + @param a The value to invert + @param b The modulus + @param c The destination (1/a mod b) + @return CRYPT_OK on success + */ + int (*invmod)(void *, void *, void *); + +/* ---- reduction ---- */ + + /** setup montgomery + @param a The modulus + @param b The destination for the reduction digit + @return CRYPT_OK on success + */ + int (*montgomery_setup)(void *a, void **b); + + /** get normalization value + @param a The destination for the normalization value + @param b The modulus + @return CRYPT_OK on success + */ + int (*montgomery_normalization)(void *a, void *b); + + /** reduce a number + @param a The number [and dest] to reduce + @param b The modulus + @param c The value "b" from montgomery_setup() + @return CRYPT_OK on success + */ + int (*montgomery_reduce)(void *a, void *b, void *c); + + /** clean up (frees memory) + @param a The value "b" from montgomery_setup() + @return CRYPT_OK on success + */ + void (*montgomery_deinit)(void *a); + +/* ---- exponentiation ---- */ + + /** Modular exponentiation + @param a The base integer + @param b The power (can be negative) integer + @param c The modulus integer + @param d The destination + @return CRYPT_OK on success + */ + int (*exptmod)(void *a, void *b, void *c, void *d); + + /** Primality testing + @param a The integer to test + @param b The destination of the result (FP_YES if prime) + @return CRYPT_OK on success + */ + int (*isprime)(void *a, int *b); + +/* ---- (optional) ecc point math ---- */ + + /** ECC GF(p) point multiplication (from the NIST curves) + @param k The integer to multiply the point by + @param G The point to multiply + @param R The destination for kG + @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 *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 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 *modulus, void *mp); + + /** ECC GF(p) point double + @param P The first point + @param R The destination of 2P + @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 *modulus, void *mp); + + /** ECC mapping from projective to affine, currently uses (x,y,z) => (x/z^2, y/z^3, 1) + @param P The point to map + @param modulus The modulus + @param mp The "b" value from montgomery_setup() + @return CRYPT_OK on success + @remark The mapping can be different but keep in mind a ecc_point only has three + integers (x,y,z) so if you use a different mapping you have to make it fit. + */ + int (*ecc_map)(ecc_point *P, void *modulus, void *mp); + + /** Computes kA*A + kB*B = C using Shamir's Trick + @param A First point to multiply + @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 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 *modulus); + +/* ---- (optional) rsa optimized math (for internal CRT) ---- */ + + /** RSA Key Generation + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param size The size of the modulus (key size) desired (octets) + @param e The "e" value (public key). e==65537 is a good choice + @param key [out] Destination of a newly created private key pair + @return CRYPT_OK if successful, upon error all allocated ram is freed + */ + int (*rsa_keygen)(prng_state *prng, int wprng, int size, long e, rsa_key *key); + + + /** RSA exponentiation + @param in The octet array representing the base + @param inlen The length of the input + @param out The destination (to be stored in an octet array format) + @param outlen The length of the output buffer and the resulting size (zero padded to the size of the modulus) + @param which PK_PUBLIC for public RSA and PK_PRIVATE for private RSA + @param key The RSA key to use + @return CRYPT_OK on success + */ + int (*rsa_me)(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int which, + rsa_key *key); +} ltc_math_descriptor; + +extern ltc_math_descriptor ltc_mp; + +int ltc_init_multi(void **a, ...); +void ltc_deinit_multi(void *a, ...); + +#ifdef LTM_DESC +extern const ltc_math_descriptor ltm_desc; +#endif + +#ifdef TFM_DESC +extern const ltc_math_descriptor tfm_desc; +#endif + +#ifdef GMP_DESC +extern const ltc_math_descriptor gmp_desc; +#endif + +#if !defined(DESC_DEF_ONLY) && defined(LTC_SOURCE) + +#define MP_DIGIT_BIT ltc_mp.bits_per_digit + +/* some handy macros */ +#define mp_init(a) ltc_mp.init(a) +#define mp_init_multi ltc_init_multi +#define mp_clear(a) ltc_mp.deinit(a) +#define mp_clear_multi ltc_deinit_multi +#define mp_init_copy(a, b) ltc_mp.init_copy(a, b) + +#define mp_neg(a, b) ltc_mp.neg(a, b) +#define mp_copy(a, b) ltc_mp.copy(a, b) + +#define mp_set(a, b) ltc_mp.set_int(a, b) +#define mp_set_int(a, b) ltc_mp.set_int(a, b) +#define mp_get_int(a) ltc_mp.get_int(a) +#define mp_get_digit(a, n) ltc_mp.get_digit(a, n) +#define mp_get_digit_count(a) ltc_mp.get_digit_count(a) +#define mp_cmp(a, b) ltc_mp.compare(a, b) +#define mp_cmp_d(a, b) ltc_mp.compare_d(a, b) +#define mp_count_bits(a) ltc_mp.count_bits(a) +#define mp_cnt_lsb(a) ltc_mp.count_lsb_bits(a) +#define mp_2expt(a, b) ltc_mp.twoexpt(a, b) + +#define mp_read_radix(a, b, c) ltc_mp.read_radix(a, b, c) +#define mp_toradix(a, b, c) ltc_mp.write_radix(a, b, c) +#define mp_unsigned_bin_size(a) ltc_mp.unsigned_size(a) +#define mp_to_unsigned_bin(a, b) ltc_mp.unsigned_write(a, b) +#define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c) + +#define mp_add(a, b, c) ltc_mp.add(a, b, c) +#define mp_add_d(a, b, c) ltc_mp.addi(a, b, c) +#define mp_sub(a, b, c) ltc_mp.sub(a, b, c) +#define mp_sub_d(a, b, c) ltc_mp.subi(a, b, c) +#define mp_mul(a, b, c) ltc_mp.mul(a, b, c) +#define mp_mul_d(a, b, c) ltc_mp.muli(a, b, c) +#define mp_sqr(a, b) ltc_mp.sqr(a, b) +#define mp_div(a, b, c, d) ltc_mp.mpdiv(a, b, c, d) +#define mp_div_2(a, b) ltc_mp.div_2(a, b) +#define mp_mod(a, b, c) ltc_mp.mod(a, b, c) +#define mp_mod_d(a, b, c) ltc_mp.modi(a, b, c) +#define mp_gcd(a, b, c) ltc_mp.gcd(a, b, c) +#define mp_lcm(a, b, c) ltc_mp.lcm(a, b, c) + +#define mp_mulmod(a, b, c, d) ltc_mp.mulmod(a, b, c, d) +#define mp_sqrmod(a, b, c) ltc_mp.sqrmod(a, b, c) +#define mp_invmod(a, b, c) ltc_mp.invmod(a, b, c) + +#define mp_montgomery_setup(a, b) ltc_mp.montgomery_setup(a, b) +#define mp_montgomery_normalization(a, b) ltc_mp.montgomery_normalization(a, b) +#define mp_montgomery_reduce(a, b, c) ltc_mp.montgomery_reduce(a, b, c) +#define mp_montgomery_free(a) ltc_mp.montgomery_deinit(a) + +#define mp_exptmod(a,b,c,d) ltc_mp.exptmod(a,b,c,d) +#define mp_prime_is_prime(a, b, c) ltc_mp.isprime(a, c) + +#define mp_iszero(a) (mp_cmp_d(a, 0) == LTC_MP_EQ ? LTC_MP_YES : LTC_MP_NO) +#define mp_isodd(a) (mp_get_digit_count(a) > 0 ? (mp_get_digit(a, 0) & 1 ? LTC_MP_YES : LTC_MP_NO) : LTC_MP_NO) +#define mp_exch(a, b) do { void *ABC__tmp = a; a = b; b = ABC__tmp; } while(0); + +#define mp_tohex(a, b) mp_toradix(a, b, 16) + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_math.h,v $ */ +/* $Revision: 1.44 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/include/tomcrypt_misc.h b/core/lib/libtomcrypt/include/tomcrypt_misc.h new file mode 100644 index 00000000000..0fc49869cf8 --- /dev/null +++ b/core/lib/libtomcrypt/include/tomcrypt_misc.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* ---- LTC_BASE64 Routines ---- */ +#ifdef LTC_BASE64 +int base64_encode(const unsigned char *in, unsigned long len, + unsigned char *out, unsigned long *outlen); + +int base64_decode(const unsigned char *in, unsigned long len, + unsigned char *out, unsigned long *outlen); +#endif + +/* ---- MEM routines ---- */ +void zeromem(void *dst, size_t len); +void burn_stack(unsigned long len); + +const char *error_to_string(int err); + +extern const char *crypt_build_settings; + +/* ---- HMM ---- */ +int crypt_fsa(void *mp, ...); + +/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_misc.h,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/include/tomcrypt_mpa.h b/core/lib/libtomcrypt/include/tomcrypt_mpa.h new file mode 100644 index 00000000000..be569c44980 --- /dev/null +++ b/core/lib/libtomcrypt/include/tomcrypt_mpa.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TOMCRYPT_MPA_H_ +#define TOMCRYPT_MPA_H_ + +#include +#include "tomcrypt.h" + +extern mpa_scratch_mem external_mem_pool; + +void init_mpa_tomcrypt(mpa_scratch_mem pool); + +#endif /* TOMCRYPT_MPA_H_ */ diff --git a/core/lib/libtomcrypt/include/tomcrypt_pk.h b/core/lib/libtomcrypt/include/tomcrypt_pk.h new file mode 100644 index 00000000000..841530cf11e --- /dev/null +++ b/core/lib/libtomcrypt/include/tomcrypt_pk.h @@ -0,0 +1,603 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* ---- NUMBER THEORY ---- */ + +enum { + PK_PUBLIC=0, + PK_PRIVATE=1 +}; + +int rand_prime(void *N, long len, prng_state *prng, int wprng); + +/* ---- RSA ---- */ +#ifdef LTC_MRSA + +/* Min and Max RSA key sizes (in bits) */ +#define MIN_RSA_SIZE 256 +#define MAX_RSA_SIZE 4096 + +/** RSA LTC_PKCS style key */ +typedef struct Rsa_key { + /** Type of key, PK_PRIVATE or PK_PUBLIC */ + int type; + /** The public exponent */ + void *e; + /** The private exponent */ + void *d; + /** The modulus */ + void *N; + /** The p factor of N */ + void *p; + /** The q factor of N */ + void *q; + /** The 1/q mod p CRT param */ + void *qP; + /** The d mod (p - 1) CRT param */ + void *dP; + /** The d mod (q - 1) CRT param */ + void *dQ; +} rsa_key; + +int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key); + +int rsa_exptmod(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int which, + rsa_key *key); + +void rsa_free(rsa_key *key); + +/* These use LTC_PKCS #1 v2.0 padding */ +#define rsa_encrypt_key(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _prng, _prng_idx, _hash_idx, _key) \ + rsa_encrypt_key_ex(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _prng, _prng_idx, _hash_idx, LTC_LTC_PKCS_1_OAEP, _key) + +#define rsa_decrypt_key(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash_idx, _stat, _key) \ + rsa_decrypt_key_ex(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash_idx, LTC_LTC_PKCS_1_OAEP, _stat, _key) + +#define rsa_sign_hash(_in, _inlen, _out, _outlen, _prng, _prng_idx, _hash_idx, _saltlen, _key) \ + rsa_sign_hash_ex(_in, _inlen, _out, _outlen, LTC_LTC_PKCS_1_PSS, _prng, _prng_idx, _hash_idx, _saltlen, _key) + +#define rsa_verify_hash(_sig, _siglen, _hash, _hashlen, _hash_idx, _saltlen, _stat, _key) \ + rsa_verify_hash_ex(_sig, _siglen, _hash, _hashlen, LTC_LTC_PKCS_1_PSS, _hash_idx, _saltlen, _stat, _key) + +/* These can be switched between LTC_PKCS #1 v2.x and LTC_PKCS #1 v1.5 paddings */ +int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const unsigned char *lparam, unsigned long lparamlen, + prng_state *prng, int prng_idx, int hash_idx, int padding, rsa_key *key); + +int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const unsigned char *lparam, unsigned long lparamlen, + int hash_idx, int padding, + int *stat, rsa_key *key); + +int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + int padding, + prng_state *prng, int prng_idx, + int hash_idx, unsigned long saltlen, + rsa_key *key); + +int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int padding, + int hash_idx, unsigned long saltlen, + int *stat, rsa_key *key); + +/* LTC_PKCS #1 import/export */ +int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key); +int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key); + +#endif + +/* ---- Katja ---- */ +#ifdef MKAT + +/* Min and Max KAT key sizes (in bits) */ +#define MIN_KAT_SIZE 1024 +#define MAX_KAT_SIZE 4096 + +/** Katja LTC_PKCS style key */ +typedef struct KAT_key { + /** Type of key, PK_PRIVATE or PK_PUBLIC */ + int type; + /** The private exponent */ + void *d; + /** The modulus */ + void *N; + /** The p factor of N */ + void *p; + /** The q factor of N */ + void *q; + /** The 1/q mod p CRT param */ + void *qP; + /** The d mod (p - 1) CRT param */ + void *dP; + /** The d mod (q - 1) CRT param */ + void *dQ; + /** The pq param */ + void *pq; +} katja_key; + +int katja_make_key(prng_state *prng, int wprng, int size, katja_key *key); + +int katja_exptmod(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int which, + katja_key *key); + +void katja_free(katja_key *key); + +/* These use LTC_PKCS #1 v2.0 padding */ +int katja_encrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const unsigned char *lparam, unsigned long lparamlen, + prng_state *prng, int prng_idx, int hash_idx, katja_key *key); + +int katja_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const unsigned char *lparam, unsigned long lparamlen, + int hash_idx, int *stat, + katja_key *key); + +/* LTC_PKCS #1 import/export */ +int katja_export(unsigned char *out, unsigned long *outlen, int type, katja_key *key); +int katja_import(const unsigned char *in, unsigned long inlen, katja_key *key); + +#endif + +/* + * From libtomcrypt.org: + * DH vanished because nobody used it and it was a pain to support + * DH support has been taken from + * http://dev.openaos.org/browser/trunk/buildroot/gen7/buildroot/package/libtomcrypt/libtomcrypt-dh.patch + */ +#ifdef LTC_LINARO_FIX_DH +/* ---- DH Routines ---- */ +#ifdef LTC_MDH + +typedef struct Dh_key { + int type; /* Type of key, PK_PRIVATE or PK_PUBLIC */ + void *x; /* private key */ + void *y; /* public key - is g^x [p] */ + void *g; /* base */ + void *p; /* prime */ +} dh_key; + +int dh_make_key(prng_state *prng, int wprng, void *q, int xbits, dh_key *key); +void dh_free(dh_key *key); +int dh_shared_secret(dh_key *private_key, void *public_key, void *secret); +#endif +#endif + +/* ---- ECC Routines ---- */ +#ifdef LTC_MECC + +/* size of our temp buffers for exported keys */ +#define ECC_BUF_SIZE 256 + +/* max private key size */ +#define ECC_MAXSIZE 66 + +/** Structure defines a NIST GF(p) curve */ +typedef struct { + /** The size of the curve in octets */ + int size; + + /** name of curve */ + const char *name; + + /** The prime that defines the field the curve is in (encoded in hex) */ + const char *prime; + + /** The fields B param (hex) */ + const char *B; + + /** The order of the curve (hex) */ + const char *order; + + /** The x co-ordinate of the base point on the curve (hex) */ + const char *Gx; + + /** The y co-ordinate of the base point on the curve (hex) */ + const char *Gy; +} 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 */ +typedef struct { + /** The x co-ordinate */ + void *x; + + /** The y co-ordinate */ + void *y; + + /** The z co-ordinate */ + void *z; +} ecc_point; + +/** 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; + + /** 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 */ + ecc_point pubkey; + + /** The private key */ + void *k; +} ecc_key; + +/** the ECC params provided */ +extern const ltc_ecc_set_type ltc_ecc_sets[]; + +int ecc_test(void); +void ecc_sizes(int *low, int *high); +int ecc_get_size(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); +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_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_shared_secret(ecc_key *private_key, ecc_key *public_key, + unsigned char *out, unsigned long *outlen); + +int ecc_encrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, int hash, + ecc_key *key); + +int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + ecc_key *key); + +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 ecc_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, 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); + +/* point ops (mp == montgomery digit) */ +#if !defined(LTC_MECC_ACCEL) || defined(LTM_LTC_DESC) || defined(GMP_LTC_DESC) +/* R = 2P */ +int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void *mp); + +/* R = P + Q */ +int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp); +#endif + +#if defined(LTC_MECC_FP) +/* optimized point multiplication using fixed point cache (HAC algorithm 14.117) */ +int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map); + +/* functions for saving/loading/freeing/adding to fixed point cache */ +int ltc_ecc_fp_save_state(unsigned char **out, unsigned long *outlen); +int ltc_ecc_fp_restore_state(unsigned char *in, unsigned long inlen); +void ltc_ecc_fp_free(void); +int ltc_ecc_fp_add_point(ecc_point *g, void *modulus, int lock); + +/* lock/unlock all points currently in fixed point cache */ +void ltc_ecc_fp_tablelock(int lock); +#endif + +/* R = kG */ +int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, 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 *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 *modulus); +#endif + +#endif + + +/* map P to affine from projective */ +int ltc_ecc_map(ecc_point *P, void *modulus, void *mp); + +#endif + +#ifdef LTC_MDSA + +/* Max diff between group and modulus size in bytes */ +#define LTC_MDSA_DELTA 512 + +/* Max DSA group size in bytes (default allows 4k-bit groups) */ +#define LTC_MDSA_MAX_GROUP 512 + +/** DSA key structure */ +typedef struct { + /** The key type, PK_PRIVATE or PK_PUBLIC */ + int type; + + /** The order of the sub-group used in octets */ + int qord; + + /** The generator */ + void *g; + + /** The prime used to generate the sub-group */ + void *q; + + /** The large prime that generats the field the contains the sub-group */ + void *p; + + /** The private key */ + void *x; + + /** The public key */ + void *y; +} dsa_key; + +int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key); +void dsa_free(dsa_key *key); + +int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen, + void *r, void *s, + prng_state *prng, int wprng, dsa_key *key); + +int dsa_sign_hash(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, dsa_key *key); + +int dsa_verify_hash_raw( void *r, void *s, + const unsigned char *hash, unsigned long hashlen, + int *stat, dsa_key *key); + +int dsa_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, dsa_key *key); + +int dsa_encrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, int hash, + dsa_key *key); + +int dsa_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + dsa_key *key); + +int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key); +int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key); +int dsa_verify_key(dsa_key *key, int *stat); + +int dsa_shared_secret(void *private_key, void *base, + dsa_key *public_key, + unsigned char *out, unsigned long *outlen); +#endif + +#ifdef LTC_DER +/* DER handling */ + +enum { + LTC_ASN1_EOL, + LTC_ASN1_BOOLEAN, + LTC_ASN1_INTEGER, + LTC_ASN1_SHORT_INTEGER, + LTC_ASN1_BIT_STRING, + LTC_ASN1_OCTET_STRING, + LTC_ASN1_NULL, + LTC_ASN1_OBJECT_IDENTIFIER, + LTC_ASN1_IA5_STRING, + LTC_ASN1_PRINTABLE_STRING, + LTC_ASN1_UTF8_STRING, + LTC_ASN1_UTCTIME, + LTC_ASN1_CHOICE, + LTC_ASN1_SEQUENCE, + LTC_ASN1_SET, + LTC_ASN1_SETOF +}; + +/** A LTC ASN.1 list type */ +typedef struct ltc_asn1_list_ { + /** The LTC ASN.1 enumerated type identifier */ + int type; + /** The data to encode or place for decoding */ + 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 */ + int used; + /** prev/next entry in the list */ + struct ltc_asn1_list_ *prev, *next, *child, *parent; +} ltc_asn1_list; + +#define LTC_SET_ASN1(list, index, Type, Data, Size) \ + do { \ + int LTC_MACRO_temp = (index); \ + ltc_asn1_list *LTC_MACRO_list = (list); \ + LTC_MACRO_list[LTC_MACRO_temp].type = (Type); \ + 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; \ + } while (0); + +/* 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) + +int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, + ltc_asn1_list *list, unsigned long outlen, int ordered); + +#define der_decode_sequence(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, 1) + +int der_length_sequence(ltc_asn1_list *list, unsigned long inlen, + unsigned long *outlen); + +/* SET */ +#define der_decode_set(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, 0) +#define der_length_set der_length_sequence +int der_encode_set(ltc_asn1_list *list, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +int der_encode_setof(ltc_asn1_list *list, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +/* VA list handy helpers with triplets of */ +int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...); +int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...); + +/* FLEXI DECODER handle unknown list decoder */ +int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out); +void der_free_sequence_flexi(ltc_asn1_list *list); +void der_sequence_free(ltc_asn1_list *in); + +/* BOOLEAN */ +int der_length_boolean(unsigned long *outlen); +int der_encode_boolean(int in, + unsigned char *out, unsigned long *outlen); +int der_decode_boolean(const unsigned char *in, unsigned long inlen, + int *out); +/* INTEGER */ +int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen); +int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num); +int der_length_integer(void *num, unsigned long *len); + +/* INTEGER -- handy for 0..2^32-1 values */ +int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsigned long *num); +int der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen); +int der_length_short_integer(unsigned long num, unsigned long *outlen); + +/* BIT STRING */ +int der_encode_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_decode_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_length_bit_string(unsigned long nbits, unsigned long *outlen); + +/* OCTET STRING */ +int der_encode_octet_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_decode_octet_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_length_octet_string(unsigned long noctets, unsigned long *outlen); + +/* OBJECT IDENTIFIER */ +int der_encode_object_identifier(unsigned long *words, unsigned long nwords, + unsigned char *out, unsigned long *outlen); +int der_decode_object_identifier(const unsigned char *in, unsigned long inlen, + unsigned long *words, unsigned long *outlen); +int der_length_object_identifier(unsigned long *words, unsigned long nwords, unsigned long *outlen); +unsigned long der_object_identifier_bits(unsigned long x); + +/* IA5 STRING */ +int der_encode_ia5_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_decode_ia5_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen); + +int der_ia5_char_encode(int c); +int der_ia5_value_decode(int v); + +/* Printable STRING */ +int der_encode_printable_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_decode_printable_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen); + +int der_printable_char_encode(int c); +int der_printable_value_decode(int v); + +/* UTF-8 */ +#if (defined(SIZE_MAX) || __STDC_VERSION__ >= 199901L || defined(WCHAR_MAX) || defined(_WCHAR_T) || defined(_WCHAR_T_DEFINED) || defined (__WCHAR_TYPE__)) && !defined(LTC_NO_WCHAR) +#include +#else +typedef ulong32 wchar_t; +#endif + +int der_encode_utf8_string(const wchar_t *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +int der_decode_utf8_string(const unsigned char *in, unsigned long inlen, + wchar_t *out, unsigned long *outlen); +unsigned long der_utf8_charsize(const wchar_t c); +int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen); + + +/* CHOICE */ +int der_decode_choice(const unsigned char *in, unsigned long *inlen, + ltc_asn1_list *list, unsigned long outlen); + +/* UTCTime */ +typedef struct { + unsigned YY, /* year */ + MM, /* month */ + DD, /* day */ + hh, /* hour */ + mm, /* minute */ + ss, /* second */ + off_dir, /* timezone offset direction 0 == +, 1 == - */ + off_hh, /* timezone offset hours */ + off_mm; /* timezone offset minutes */ +} ltc_utctime; + +int der_encode_utctime(ltc_utctime *utctime, + unsigned char *out, unsigned long *outlen); + +int der_decode_utctime(const unsigned char *in, unsigned long *inlen, + ltc_utctime *out); + +int der_length_utctime(ltc_utctime *utctime, unsigned long *outlen); + + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_pk.h,v $ */ +/* $Revision: 1.81 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/include/tomcrypt_pkcs.h b/core/lib/libtomcrypt/include/tomcrypt_pkcs.h new file mode 100644 index 00000000000..054898e658b --- /dev/null +++ b/core/lib/libtomcrypt/include/tomcrypt_pkcs.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* LTC_PKCS Header Info */ + +/* ===> LTC_PKCS #1 -- RSA Cryptography <=== */ +#ifdef LTC_PKCS_1 + +enum ltc_pkcs_1_v1_5_blocks +{ + LTC_LTC_PKCS_1_EMSA = 1, /* Block type 1 (LTC_PKCS #1 v1.5 signature padding) */ + LTC_LTC_PKCS_1_EME = 2 /* Block type 2 (LTC_PKCS #1 v1.5 encryption padding) */ +}; + +enum ltc_pkcs_1_paddings +{ + LTC_LTC_PKCS_1_V1_5 = 1, /* LTC_PKCS #1 v1.5 padding (\sa ltc_pkcs_1_v1_5_blocks) */ + LTC_LTC_PKCS_1_OAEP = 2, /* LTC_PKCS #1 v2.0 encryption padding */ + LTC_LTC_PKCS_1_PSS = 3 /* LTC_PKCS #1 v2.1 signature padding */ +}; + +int pkcs_1_mgf1( int hash_idx, + const unsigned char *seed, unsigned long seedlen, + unsigned char *mask, unsigned long masklen); + +int pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out); +int pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen); + +/* *** v1.5 padding */ +int pkcs_1_v1_5_encode(const unsigned char *msg, + unsigned long msglen, + int block_type, + unsigned long modulus_bitlen, + prng_state *prng, + int prng_idx, + unsigned char *out, + unsigned long *outlen); + +int pkcs_1_v1_5_decode(const unsigned char *msg, + unsigned long msglen, + int block_type, + unsigned long modulus_bitlen, + unsigned char *out, + unsigned long *outlen, + int *is_valid); + +/* *** v2.1 padding */ +int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, + const unsigned char *lparam, unsigned long lparamlen, + unsigned long modulus_bitlen, prng_state *prng, + int prng_idx, int hash_idx, + unsigned char *out, unsigned long *outlen); + +int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, + const unsigned char *lparam, unsigned long lparamlen, + unsigned long modulus_bitlen, int hash_idx, + unsigned char *out, unsigned long *outlen, + int *res); + +int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, + unsigned long saltlen, prng_state *prng, + int prng_idx, int hash_idx, + unsigned long modulus_bitlen, + unsigned char *out, unsigned long *outlen); + +int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, + const unsigned char *sig, unsigned long siglen, + unsigned long saltlen, int hash_idx, + unsigned long modulus_bitlen, int *res); + +#endif /* LTC_PKCS_1 */ + +/* ===> LTC_PKCS #5 -- Password Based Cryptography <=== */ +#ifdef LTC_PKCS_5 + +/* Algorithm #1 (old) */ +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); + +/* Algorithm #2 (new) */ +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); + +#endif /* LTC_PKCS_5 */ + +/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_pkcs.h,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/include/tomcrypt_prng.h b/core/lib/libtomcrypt/include/tomcrypt_prng.h new file mode 100644 index 00000000000..cfd4dd76744 --- /dev/null +++ b/core/lib/libtomcrypt/include/tomcrypt_prng.h @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* ---- PRNG Stuff ---- */ +#ifdef LTC_YARROW +struct yarrow_prng { + int cipher, hash; + unsigned char pool[MAXBLOCKSIZE]; + symmetric_CTR ctr; + LTC_MUTEX_TYPE(prng_lock) +}; +#endif + +#ifdef LTC_RC4 +struct rc4_prng { + int x, y; + unsigned char buf[256]; +}; +#endif + +#ifdef LTC_FORTUNA +struct fortuna_prng { + hash_state pool[LTC_FORTUNA_POOLS]; /* the pools */ + + symmetric_key skey; + + unsigned char K[32], /* the current key */ + IV[16]; /* IV for CTR mode */ + + unsigned long pool_idx, /* current pool we will add to */ + pool0_len, /* length of 0'th pool */ + wd; + + ulong64 reset_cnt; /* number of times we have reset */ + LTC_MUTEX_TYPE(prng_lock) +}; +#endif + +#ifdef LTC_SOBER128 +struct sober128_prng { + ulong32 R[17], /* Working storage for the shift register */ + initR[17], /* saved register contents */ + konst, /* key dependent constant */ + sbuf; /* partial word encryption buffer */ + + int nbuf, /* number of part-word stream bits buffered */ + flag, /* first add_entropy call or not? */ + set; /* did we call add_entropy to set key? */ + +}; +#endif + +typedef union Prng_state { + char dummy[1]; +#ifdef LTC_YARROW + struct yarrow_prng yarrow; +#endif +#ifdef LTC_RC4 + struct rc4_prng rc4; +#endif +#ifdef LTC_FORTUNA + struct fortuna_prng fortuna; +#endif +#ifdef LTC_SOBER128 + struct sober128_prng sober128; +#endif +} prng_state; + +/** PRNG descriptor */ +extern struct ltc_prng_descriptor { + /** Name of the PRNG */ + const char *name; + /** size in bytes of exported state */ + int export_size; + /** Start a PRNG state + @param prng [out] The state to initialize + @return CRYPT_OK if successful + */ + int (*start)(prng_state *prng); + /** Add entropy to the PRNG + @param in The entropy + @param inlen Length of the entropy (octets)\ + @param prng The PRNG state + @return CRYPT_OK if successful + */ + int (*add_entropy)(const unsigned char *in, unsigned long inlen, prng_state *prng); + /** Ready a PRNG state to read from + @param prng The PRNG state to ready + @return CRYPT_OK if successful + */ + int (*ready)(prng_state *prng); + /** Read from the PRNG + @param out [out] Where to store the data + @param outlen Length of data desired (octets) + @param prng The PRNG state to read from + @return Number of octets read + */ + unsigned long (*read)(unsigned char *out, unsigned long outlen, prng_state *prng); + /** Terminate a PRNG state + @param prng The PRNG state to terminate + @return CRYPT_OK if successful + */ + int (*done)(prng_state *prng); + /** Export a PRNG state + @param out [out] The destination for the state + @param outlen [in/out] The max size and resulting size of the PRNG state + @param prng The PRNG to export + @return CRYPT_OK if successful + */ + int (*pexport)(unsigned char *out, unsigned long *outlen, prng_state *prng); + /** Import a PRNG state + @param in The data to import + @param inlen The length of the data to import (octets) + @param prng The PRNG to initialize/import + @return CRYPT_OK if successful + */ + int (*pimport)(const unsigned char *in, unsigned long inlen, prng_state *prng); + /** Self-test the PRNG + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled + */ + int (*test)(void); +} prng_descriptor[]; + +#ifdef LTC_YARROW +int yarrow_start(prng_state *prng); +int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); +int yarrow_ready(prng_state *prng); +unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng); +int yarrow_done(prng_state *prng); +int yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng); +int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng); +int yarrow_test(void); +extern const struct ltc_prng_descriptor yarrow_desc; +#endif + +#ifdef LTC_FORTUNA +int fortuna_start(prng_state *prng); +int fortuna_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); +int fortuna_ready(prng_state *prng); +unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state *prng); +int fortuna_done(prng_state *prng); +int fortuna_export(unsigned char *out, unsigned long *outlen, prng_state *prng); +int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng); +int fortuna_test(void); +extern const struct ltc_prng_descriptor fortuna_desc; +#endif + +#ifdef LTC_RC4 +int rc4_start(prng_state *prng); +int rc4_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); +int rc4_ready(prng_state *prng); +unsigned long rc4_read(unsigned char *out, unsigned long outlen, prng_state *prng); +int rc4_done(prng_state *prng); +int rc4_export(unsigned char *out, unsigned long *outlen, prng_state *prng); +int rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng); +int rc4_test(void); +extern const struct ltc_prng_descriptor rc4_desc; +#endif + +#ifdef LTC_SPRNG +int sprng_start(prng_state *prng); +int sprng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); +int sprng_ready(prng_state *prng); +unsigned long sprng_read(unsigned char *out, unsigned long outlen, prng_state *prng); +int sprng_done(prng_state *prng); +int sprng_export(unsigned char *out, unsigned long *outlen, prng_state *prng); +int sprng_import(const unsigned char *in, unsigned long inlen, prng_state *prng); +int sprng_test(void); +extern const struct ltc_prng_descriptor sprng_desc; +#endif + +#ifdef LTC_SOBER128 +int sober128_start(prng_state *prng); +int sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); +int sober128_ready(prng_state *prng); +unsigned long sober128_read(unsigned char *out, unsigned long outlen, prng_state *prng); +int sober128_done(prng_state *prng); +int sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng); +int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng); +int sober128_test(void); +extern const struct ltc_prng_descriptor sober128_desc; +#endif + +int find_prng(const char *name); +int register_prng(const struct ltc_prng_descriptor *prng); +int unregister_prng(const struct ltc_prng_descriptor *prng); +int prng_is_valid(int idx); +LTC_MUTEX_PROTO(ltc_prng_mutex) + +/* Slow RNG you **might** be able to use to seed a PRNG with. Be careful as this + * might not work on all platforms as planned + */ +unsigned long rng_get_bytes(unsigned char *out, + unsigned long outlen, + void (*callback)(void)); + +int rng_make_prng(int bits, int wprng, prng_state *prng, void (*callback)(void)); + + +/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_prng.h,v $ */ +/* $Revision: 1.9 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/ciphers/aes.c b/core/lib/libtomcrypt/src/ciphers/aes.c new file mode 100644 index 00000000000..a01b1ef1148 --- /dev/null +++ b/core/lib/libtomcrypt/src/ciphers/aes.c @@ -0,0 +1,787 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* AES implementation by Tom St Denis + * + * Derived from the Public Domain source code by + +--- + * rijndael-alg-fst.c + * + * @version 3.0 (December 2000) + * + * Optimised ANSI C code for the Rijndael cipher (now AES) + * + * @author Vincent Rijmen + * @author Antoon Bosselaers + * @author Paulo Barreto +--- + */ +/** + @file aes.c + Implementation of AES +*/ + +#include "tomcrypt.h" + +#ifdef LTC_RIJNDAEL + +#ifndef ENCRYPT_ONLY + +#define SETUP rijndael_setup +#define ECB_ENC rijndael_ecb_encrypt +#define ECB_DEC rijndael_ecb_decrypt +#define ECB_DONE rijndael_done +#define ECB_TEST rijndael_test +#define ECB_KS rijndael_keysize + +const struct ltc_cipher_descriptor rijndael_desc = +{ + "rijndael", + 6, + 16, 32, 16, 10, + SETUP, ECB_ENC, ECB_DEC, ECB_TEST, ECB_DONE, ECB_KS, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +const struct ltc_cipher_descriptor aes_desc = +{ + "aes", + 6, + 16, 32, 16, 10, + SETUP, ECB_ENC, ECB_DEC, ECB_TEST, ECB_DONE, ECB_KS, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +#else + +#define SETUP rijndael_enc_setup +#define ECB_ENC rijndael_enc_ecb_encrypt +#define ECB_KS rijndael_enc_keysize +#define ECB_DONE rijndael_enc_done + +const struct ltc_cipher_descriptor rijndael_enc_desc = +{ + "rijndael", + 6, + 16, 32, 16, 10, + SETUP, ECB_ENC, NULL, NULL, ECB_DONE, ECB_KS, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +const struct ltc_cipher_descriptor aes_enc_desc = +{ + "aes", + 6, + 16, 32, 16, 10, + SETUP, ECB_ENC, NULL, NULL, ECB_DONE, ECB_KS, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +#endif + +#include "aes_tab.c" + +static ulong32 setup_mix(ulong32 temp) +{ + return (Te4_3[byte(temp, 2)]) ^ + (Te4_2[byte(temp, 1)]) ^ + (Te4_1[byte(temp, 0)]) ^ + (Te4_0[byte(temp, 3)]); +} + +#ifndef ENCRYPT_ONLY +#ifdef LTC_SMALL_CODE +static ulong32 setup_mix2(ulong32 temp) +{ + return Td0(255 & Te4[byte(temp, 3)]) ^ + Td1(255 & Te4[byte(temp, 2)]) ^ + Td2(255 & Te4[byte(temp, 1)]) ^ + Td3(255 & Te4[byte(temp, 0)]); +} +#endif +#endif + + /** + Initialize the AES (Rijndael) block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful + */ +int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + int i, j; + ulong32 temp, *rk; +#ifndef ENCRYPT_ONLY + ulong32 *rrk; +#endif + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if (keylen != 16 && keylen != 24 && keylen != 32) { + return CRYPT_INVALID_KEYSIZE; + } + + if (num_rounds != 0 && num_rounds != (10 + ((keylen/8)-2)*2)) { + return CRYPT_INVALID_ROUNDS; + } + + skey->rijndael.Nr = 10 + ((keylen/8)-2)*2; + + /* setup the forward key */ + i = 0; + rk = skey->rijndael.eK; + LOAD32H(rk[0], key ); + LOAD32H(rk[1], key + 4); + LOAD32H(rk[2], key + 8); + LOAD32H(rk[3], key + 12); + if (keylen == 16) { + j = 44; + for (;;) { + temp = rk[3]; + rk[4] = rk[0] ^ setup_mix(temp) ^ rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) { + break; + } + rk += 4; + } + } else if (keylen == 24) { + j = 52; + LOAD32H(rk[4], key + 16); + LOAD32H(rk[5], key + 20); + for (;;) { + #ifdef _MSC_VER + temp = skey->rijndael.eK[rk - skey->rijndael.eK + 5]; + #else + temp = rk[5]; + #endif + rk[ 6] = rk[ 0] ^ setup_mix(temp) ^ rcon[i]; + rk[ 7] = rk[ 1] ^ rk[ 6]; + rk[ 8] = rk[ 2] ^ rk[ 7]; + rk[ 9] = rk[ 3] ^ rk[ 8]; + if (++i == 8) { + break; + } + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + rk += 6; + } + } else if (keylen == 32) { + j = 60; + LOAD32H(rk[4], key + 16); + LOAD32H(rk[5], key + 20); + LOAD32H(rk[6], key + 24); + LOAD32H(rk[7], key + 28); + for (;;) { + #ifdef _MSC_VER + temp = skey->rijndael.eK[rk - skey->rijndael.eK + 7]; + #else + temp = rk[7]; + #endif + rk[ 8] = rk[ 0] ^ setup_mix(temp) ^ rcon[i]; + rk[ 9] = rk[ 1] ^ rk[ 8]; + rk[10] = rk[ 2] ^ rk[ 9]; + rk[11] = rk[ 3] ^ rk[10]; + if (++i == 7) { + break; + } + temp = rk[11]; + rk[12] = rk[ 4] ^ setup_mix(RORc(temp, 8)); + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + rk += 8; + } + } else { + /* this can't happen */ + return CRYPT_ERROR; + } + +#ifndef ENCRYPT_ONLY + /* setup the inverse key now */ + rk = skey->rijndael.dK; + rrk = skey->rijndael.eK + j - 4; + + /* apply the inverse MixColumn transform to all round keys but the first and the last: */ + /* copy first */ + *rk++ = *rrk++; + *rk++ = *rrk++; + *rk++ = *rrk++; + *rk = *rrk; + rk -= 3; rrk -= 3; + + for (i = 1; i < skey->rijndael.Nr; i++) { + rrk -= 4; + rk += 4; + #ifdef LTC_SMALL_CODE + temp = rrk[0]; + rk[0] = setup_mix2(temp); + temp = rrk[1]; + rk[1] = setup_mix2(temp); + temp = rrk[2]; + rk[2] = setup_mix2(temp); + temp = rrk[3]; + rk[3] = setup_mix2(temp); + #else + temp = rrk[0]; + rk[0] = + Tks0[byte(temp, 3)] ^ + Tks1[byte(temp, 2)] ^ + Tks2[byte(temp, 1)] ^ + Tks3[byte(temp, 0)]; + temp = rrk[1]; + rk[1] = + Tks0[byte(temp, 3)] ^ + Tks1[byte(temp, 2)] ^ + Tks2[byte(temp, 1)] ^ + Tks3[byte(temp, 0)]; + temp = rrk[2]; + rk[2] = + Tks0[byte(temp, 3)] ^ + Tks1[byte(temp, 2)] ^ + Tks2[byte(temp, 1)] ^ + Tks3[byte(temp, 0)]; + temp = rrk[3]; + rk[3] = + Tks0[byte(temp, 3)] ^ + Tks1[byte(temp, 2)] ^ + Tks2[byte(temp, 1)] ^ + Tks3[byte(temp, 0)]; + #endif + + } + + /* copy last */ + rrk -= 4; + rk += 4; + *rk++ = *rrk++; + *rk++ = *rrk++; + *rk++ = *rrk++; + *rk = *rrk; +#endif /* ENCRYPT_ONLY */ + + return CRYPT_OK; +} + +/** + Encrypts a block of text with AES + @param pt The input plaintext (16 bytes) + @param ct The output ciphertext (16 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +#ifdef LTC_CLEAN_STACK +static int _rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey) +#else +int ECB_ENC(const unsigned char *pt, unsigned char *ct, symmetric_key *skey) +#endif +{ + ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk; + int Nr, r; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + Nr = skey->rijndael.Nr; + rk = skey->rijndael.eK; + + /* + * map byte array block to cipher state + * and add initial round key: + */ + LOAD32H(s0, pt ); s0 ^= rk[0]; + LOAD32H(s1, pt + 4); s1 ^= rk[1]; + LOAD32H(s2, pt + 8); s2 ^= rk[2]; + LOAD32H(s3, pt + 12); s3 ^= rk[3]; + +#ifdef LTC_SMALL_CODE + + for (r = 0; ; r++) { + rk += 4; + t0 = + Te0(byte(s0, 3)) ^ + Te1(byte(s1, 2)) ^ + Te2(byte(s2, 1)) ^ + Te3(byte(s3, 0)) ^ + rk[0]; + t1 = + Te0(byte(s1, 3)) ^ + Te1(byte(s2, 2)) ^ + Te2(byte(s3, 1)) ^ + Te3(byte(s0, 0)) ^ + rk[1]; + t2 = + Te0(byte(s2, 3)) ^ + Te1(byte(s3, 2)) ^ + Te2(byte(s0, 1)) ^ + Te3(byte(s1, 0)) ^ + rk[2]; + t3 = + Te0(byte(s3, 3)) ^ + Te1(byte(s0, 2)) ^ + Te2(byte(s1, 1)) ^ + Te3(byte(s2, 0)) ^ + rk[3]; + if (r == Nr-2) { + break; + } + s0 = t0; s1 = t1; s2 = t2; s3 = t3; + } + rk += 4; + +#else + + /* + * Nr - 1 full rounds: + */ + r = Nr >> 1; + for (;;) { + t0 = + Te0(byte(s0, 3)) ^ + Te1(byte(s1, 2)) ^ + Te2(byte(s2, 1)) ^ + Te3(byte(s3, 0)) ^ + rk[4]; + t1 = + Te0(byte(s1, 3)) ^ + Te1(byte(s2, 2)) ^ + Te2(byte(s3, 1)) ^ + Te3(byte(s0, 0)) ^ + rk[5]; + t2 = + Te0(byte(s2, 3)) ^ + Te1(byte(s3, 2)) ^ + Te2(byte(s0, 1)) ^ + Te3(byte(s1, 0)) ^ + rk[6]; + t3 = + Te0(byte(s3, 3)) ^ + Te1(byte(s0, 2)) ^ + Te2(byte(s1, 1)) ^ + Te3(byte(s2, 0)) ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Te0(byte(t0, 3)) ^ + Te1(byte(t1, 2)) ^ + Te2(byte(t2, 1)) ^ + Te3(byte(t3, 0)) ^ + rk[0]; + s1 = + Te0(byte(t1, 3)) ^ + Te1(byte(t2, 2)) ^ + Te2(byte(t3, 1)) ^ + Te3(byte(t0, 0)) ^ + rk[1]; + s2 = + Te0(byte(t2, 3)) ^ + Te1(byte(t3, 2)) ^ + Te2(byte(t0, 1)) ^ + Te3(byte(t1, 0)) ^ + rk[2]; + s3 = + Te0(byte(t3, 3)) ^ + Te1(byte(t0, 2)) ^ + Te2(byte(t1, 1)) ^ + Te3(byte(t2, 0)) ^ + rk[3]; + } + +#endif + + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Te4_3[byte(t0, 3)]) ^ + (Te4_2[byte(t1, 2)]) ^ + (Te4_1[byte(t2, 1)]) ^ + (Te4_0[byte(t3, 0)]) ^ + rk[0]; + STORE32H(s0, ct); + s1 = + (Te4_3[byte(t1, 3)]) ^ + (Te4_2[byte(t2, 2)]) ^ + (Te4_1[byte(t3, 1)]) ^ + (Te4_0[byte(t0, 0)]) ^ + rk[1]; + STORE32H(s1, ct+4); + s2 = + (Te4_3[byte(t2, 3)]) ^ + (Te4_2[byte(t3, 2)]) ^ + (Te4_1[byte(t0, 1)]) ^ + (Te4_0[byte(t1, 0)]) ^ + rk[2]; + STORE32H(s2, ct+8); + s3 = + (Te4_3[byte(t3, 3)]) ^ + (Te4_2[byte(t0, 2)]) ^ + (Te4_1[byte(t1, 1)]) ^ + (Te4_0[byte(t2, 0)]) ^ + rk[3]; + STORE32H(s3, ct+12); + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int ECB_ENC(const unsigned char *pt, unsigned char *ct, symmetric_key *skey) +{ + int err = _rijndael_ecb_encrypt(pt, ct, skey); + burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2); + return err; +} +#endif + +#ifndef ENCRYPT_ONLY + +/** + Decrypts a block of text with AES + @param ct The input ciphertext (16 bytes) + @param pt The output plaintext (16 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +#ifdef LTC_CLEAN_STACK +static int _rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) +#else +int ECB_DEC(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) +#endif +{ + ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk; + int Nr, r; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + Nr = skey->rijndael.Nr; + rk = skey->rijndael.dK; + + /* + * map byte array block to cipher state + * and add initial round key: + */ + LOAD32H(s0, ct ); s0 ^= rk[0]; + LOAD32H(s1, ct + 4); s1 ^= rk[1]; + LOAD32H(s2, ct + 8); s2 ^= rk[2]; + LOAD32H(s3, ct + 12); s3 ^= rk[3]; + +#ifdef LTC_SMALL_CODE + for (r = 0; ; r++) { + rk += 4; + t0 = + Td0(byte(s0, 3)) ^ + Td1(byte(s3, 2)) ^ + Td2(byte(s2, 1)) ^ + Td3(byte(s1, 0)) ^ + rk[0]; + t1 = + Td0(byte(s1, 3)) ^ + Td1(byte(s0, 2)) ^ + Td2(byte(s3, 1)) ^ + Td3(byte(s2, 0)) ^ + rk[1]; + t2 = + Td0(byte(s2, 3)) ^ + Td1(byte(s1, 2)) ^ + Td2(byte(s0, 1)) ^ + Td3(byte(s3, 0)) ^ + rk[2]; + t3 = + Td0(byte(s3, 3)) ^ + Td1(byte(s2, 2)) ^ + Td2(byte(s1, 1)) ^ + Td3(byte(s0, 0)) ^ + rk[3]; + if (r == Nr-2) { + break; + } + s0 = t0; s1 = t1; s2 = t2; s3 = t3; + } + rk += 4; + +#else + + /* + * Nr - 1 full rounds: + */ + r = Nr >> 1; + for (;;) { + + t0 = + Td0(byte(s0, 3)) ^ + Td1(byte(s3, 2)) ^ + Td2(byte(s2, 1)) ^ + Td3(byte(s1, 0)) ^ + rk[4]; + t1 = + Td0(byte(s1, 3)) ^ + Td1(byte(s0, 2)) ^ + Td2(byte(s3, 1)) ^ + Td3(byte(s2, 0)) ^ + rk[5]; + t2 = + Td0(byte(s2, 3)) ^ + Td1(byte(s1, 2)) ^ + Td2(byte(s0, 1)) ^ + Td3(byte(s3, 0)) ^ + rk[6]; + t3 = + Td0(byte(s3, 3)) ^ + Td1(byte(s2, 2)) ^ + Td2(byte(s1, 1)) ^ + Td3(byte(s0, 0)) ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + + s0 = + Td0(byte(t0, 3)) ^ + Td1(byte(t3, 2)) ^ + Td2(byte(t2, 1)) ^ + Td3(byte(t1, 0)) ^ + rk[0]; + s1 = + Td0(byte(t1, 3)) ^ + Td1(byte(t0, 2)) ^ + Td2(byte(t3, 1)) ^ + Td3(byte(t2, 0)) ^ + rk[1]; + s2 = + Td0(byte(t2, 3)) ^ + Td1(byte(t1, 2)) ^ + Td2(byte(t0, 1)) ^ + Td3(byte(t3, 0)) ^ + rk[2]; + s3 = + Td0(byte(t3, 3)) ^ + Td1(byte(t2, 2)) ^ + Td2(byte(t1, 1)) ^ + Td3(byte(t0, 0)) ^ + rk[3]; + } +#endif + + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Td4[byte(t0, 3)] & 0xff000000) ^ + (Td4[byte(t3, 2)] & 0x00ff0000) ^ + (Td4[byte(t2, 1)] & 0x0000ff00) ^ + (Td4[byte(t1, 0)] & 0x000000ff) ^ + rk[0]; + STORE32H(s0, pt); + s1 = + (Td4[byte(t1, 3)] & 0xff000000) ^ + (Td4[byte(t0, 2)] & 0x00ff0000) ^ + (Td4[byte(t3, 1)] & 0x0000ff00) ^ + (Td4[byte(t2, 0)] & 0x000000ff) ^ + rk[1]; + STORE32H(s1, pt+4); + s2 = + (Td4[byte(t2, 3)] & 0xff000000) ^ + (Td4[byte(t1, 2)] & 0x00ff0000) ^ + (Td4[byte(t0, 1)] & 0x0000ff00) ^ + (Td4[byte(t3, 0)] & 0x000000ff) ^ + rk[2]; + STORE32H(s2, pt+8); + s3 = + (Td4[byte(t3, 3)] & 0xff000000) ^ + (Td4[byte(t2, 2)] & 0x00ff0000) ^ + (Td4[byte(t1, 1)] & 0x0000ff00) ^ + (Td4[byte(t0, 0)] & 0x000000ff) ^ + rk[3]; + STORE32H(s3, pt+12); + + return CRYPT_OK; +} + + +#ifdef LTC_CLEAN_STACK +int ECB_DEC(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) +{ + int err = _rijndael_ecb_decrypt(ct, pt, skey); + burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2); + return err; +} +#endif + +/** + Performs a self-test of the AES block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int ECB_TEST(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + int err; + static const struct { + int keylen; + unsigned char key[32], pt[16], ct[16]; + } tests[] = { + { 16, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, + 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a } + }, { + 24, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0, + 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 } + }, { + 32, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, + 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 } + } + }; + + symmetric_key key; + unsigned char tmp[2][16]; + int i, y; + + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + zeromem(&key, sizeof(key)); + if ((err = rijndael_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { + return err; + } + + rijndael_ecb_encrypt(tests[i].pt, tmp[0], &key); + rijndael_ecb_decrypt(tmp[0], tmp[1], &key); + if (XMEMCMP(tmp[0], tests[i].ct, 16) || XMEMCMP(tmp[1], tests[i].pt, 16)) { +#if 0 + printf("\n\nTest %d failed\n", i); + if (XMEMCMP(tmp[0], tests[i].ct, 16)) { + printf("CT: "); + for (i = 0; i < 16; i++) { + printf("%02x ", tmp[0][i]); + } + printf("\n"); + } else { + printf("PT: "); + for (i = 0; i < 16; i++) { + printf("%02x ", tmp[1][i]); + } + printf("\n"); + } +#endif + return CRYPT_FAIL_TESTVECTOR; + } + + /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ + for (y = 0; y < 16; y++) tmp[0][y] = 0; + for (y = 0; y < 1000; y++) rijndael_ecb_encrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 1000; y++) rijndael_ecb_decrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + } + return CRYPT_OK; + #endif +} + +#endif /* ENCRYPT_ONLY */ + + +/** Terminate the context + @param skey The scheduled key +*/ +void ECB_DONE(symmetric_key *skey) +{ +} + + +/** + Gets suitable key size + @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. + @return CRYPT_OK if the input key size is acceptable. +*/ +int ECB_KS(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + + if (*keysize < 16) + return CRYPT_INVALID_KEYSIZE; + if (*keysize < 24) { + *keysize = 16; + return CRYPT_OK; + } else if (*keysize < 32) { + *keysize = 24; + return CRYPT_OK; + } else { + *keysize = 32; + return CRYPT_OK; + } +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/ciphers/aes/aes.c,v $ */ +/* $Revision: 1.16 $ */ +/* $Date: 2007/05/12 14:13:00 $ */ diff --git a/core/lib/libtomcrypt/src/ciphers/aes_tab.c b/core/lib/libtomcrypt/src/ciphers/aes_tab.c new file mode 100644 index 00000000000..51a90a651de --- /dev/null +++ b/core/lib/libtomcrypt/src/ciphers/aes_tab.c @@ -0,0 +1,1057 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +/* The precomputed tables for AES */ +/* +Te0[x] = S [x].[02, 01, 01, 03]; +Te1[x] = S [x].[03, 02, 01, 01]; +Te2[x] = S [x].[01, 03, 02, 01]; +Te3[x] = S [x].[01, 01, 03, 02]; +Te4[x] = S [x].[01, 01, 01, 01]; + +Td0[x] = Si[x].[0e, 09, 0d, 0b]; +Td1[x] = Si[x].[0b, 0e, 09, 0d]; +Td2[x] = Si[x].[0d, 0b, 0e, 09]; +Td3[x] = Si[x].[09, 0d, 0b, 0e]; +Td4[x] = Si[x].[01, 01, 01, 01]; +*/ + +/** + @file aes_tab.c + AES tables +*/ +#include "tomcrypt_macros.h" + +static const ulong32 TE0[256] = { + 0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL, + 0xfff2f20dUL, 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL, + 0x60303050UL, 0x02010103UL, 0xce6767a9UL, 0x562b2b7dUL, + 0xe7fefe19UL, 0xb5d7d762UL, 0x4dababe6UL, 0xec76769aUL, + 0x8fcaca45UL, 0x1f82829dUL, 0x89c9c940UL, 0xfa7d7d87UL, + 0xeffafa15UL, 0xb25959ebUL, 0x8e4747c9UL, 0xfbf0f00bUL, + 0x41adadecUL, 0xb3d4d467UL, 0x5fa2a2fdUL, 0x45afafeaUL, + 0x239c9cbfUL, 0x53a4a4f7UL, 0xe4727296UL, 0x9bc0c05bUL, + 0x75b7b7c2UL, 0xe1fdfd1cUL, 0x3d9393aeUL, 0x4c26266aUL, + 0x6c36365aUL, 0x7e3f3f41UL, 0xf5f7f702UL, 0x83cccc4fUL, + 0x6834345cUL, 0x51a5a5f4UL, 0xd1e5e534UL, 0xf9f1f108UL, + 0xe2717193UL, 0xabd8d873UL, 0x62313153UL, 0x2a15153fUL, + 0x0804040cUL, 0x95c7c752UL, 0x46232365UL, 0x9dc3c35eUL, + 0x30181828UL, 0x379696a1UL, 0x0a05050fUL, 0x2f9a9ab5UL, + 0x0e070709UL, 0x24121236UL, 0x1b80809bUL, 0xdfe2e23dUL, + 0xcdebeb26UL, 0x4e272769UL, 0x7fb2b2cdUL, 0xea75759fUL, + 0x1209091bUL, 0x1d83839eUL, 0x582c2c74UL, 0x341a1a2eUL, + 0x361b1b2dUL, 0xdc6e6eb2UL, 0xb45a5aeeUL, 0x5ba0a0fbUL, + 0xa45252f6UL, 0x763b3b4dUL, 0xb7d6d661UL, 0x7db3b3ceUL, + 0x5229297bUL, 0xdde3e33eUL, 0x5e2f2f71UL, 0x13848497UL, + 0xa65353f5UL, 0xb9d1d168UL, 0x00000000UL, 0xc1eded2cUL, + 0x40202060UL, 0xe3fcfc1fUL, 0x79b1b1c8UL, 0xb65b5bedUL, + 0xd46a6abeUL, 0x8dcbcb46UL, 0x67bebed9UL, 0x7239394bUL, + 0x944a4adeUL, 0x984c4cd4UL, 0xb05858e8UL, 0x85cfcf4aUL, + 0xbbd0d06bUL, 0xc5efef2aUL, 0x4faaaae5UL, 0xedfbfb16UL, + 0x864343c5UL, 0x9a4d4dd7UL, 0x66333355UL, 0x11858594UL, + 0x8a4545cfUL, 0xe9f9f910UL, 0x04020206UL, 0xfe7f7f81UL, + 0xa05050f0UL, 0x783c3c44UL, 0x259f9fbaUL, 0x4ba8a8e3UL, + 0xa25151f3UL, 0x5da3a3feUL, 0x804040c0UL, 0x058f8f8aUL, + 0x3f9292adUL, 0x219d9dbcUL, 0x70383848UL, 0xf1f5f504UL, + 0x63bcbcdfUL, 0x77b6b6c1UL, 0xafdada75UL, 0x42212163UL, + 0x20101030UL, 0xe5ffff1aUL, 0xfdf3f30eUL, 0xbfd2d26dUL, + 0x81cdcd4cUL, 0x180c0c14UL, 0x26131335UL, 0xc3ecec2fUL, + 0xbe5f5fe1UL, 0x359797a2UL, 0x884444ccUL, 0x2e171739UL, + 0x93c4c457UL, 0x55a7a7f2UL, 0xfc7e7e82UL, 0x7a3d3d47UL, + 0xc86464acUL, 0xba5d5de7UL, 0x3219192bUL, 0xe6737395UL, + 0xc06060a0UL, 0x19818198UL, 0x9e4f4fd1UL, 0xa3dcdc7fUL, + 0x44222266UL, 0x542a2a7eUL, 0x3b9090abUL, 0x0b888883UL, + 0x8c4646caUL, 0xc7eeee29UL, 0x6bb8b8d3UL, 0x2814143cUL, + 0xa7dede79UL, 0xbc5e5ee2UL, 0x160b0b1dUL, 0xaddbdb76UL, + 0xdbe0e03bUL, 0x64323256UL, 0x743a3a4eUL, 0x140a0a1eUL, + 0x924949dbUL, 0x0c06060aUL, 0x4824246cUL, 0xb85c5ce4UL, + 0x9fc2c25dUL, 0xbdd3d36eUL, 0x43acacefUL, 0xc46262a6UL, + 0x399191a8UL, 0x319595a4UL, 0xd3e4e437UL, 0xf279798bUL, + 0xd5e7e732UL, 0x8bc8c843UL, 0x6e373759UL, 0xda6d6db7UL, + 0x018d8d8cUL, 0xb1d5d564UL, 0x9c4e4ed2UL, 0x49a9a9e0UL, + 0xd86c6cb4UL, 0xac5656faUL, 0xf3f4f407UL, 0xcfeaea25UL, + 0xca6565afUL, 0xf47a7a8eUL, 0x47aeaee9UL, 0x10080818UL, + 0x6fbabad5UL, 0xf0787888UL, 0x4a25256fUL, 0x5c2e2e72UL, + 0x381c1c24UL, 0x57a6a6f1UL, 0x73b4b4c7UL, 0x97c6c651UL, + 0xcbe8e823UL, 0xa1dddd7cUL, 0xe874749cUL, 0x3e1f1f21UL, + 0x964b4bddUL, 0x61bdbddcUL, 0x0d8b8b86UL, 0x0f8a8a85UL, + 0xe0707090UL, 0x7c3e3e42UL, 0x71b5b5c4UL, 0xcc6666aaUL, + 0x904848d8UL, 0x06030305UL, 0xf7f6f601UL, 0x1c0e0e12UL, + 0xc26161a3UL, 0x6a35355fUL, 0xae5757f9UL, 0x69b9b9d0UL, + 0x17868691UL, 0x99c1c158UL, 0x3a1d1d27UL, 0x279e9eb9UL, + 0xd9e1e138UL, 0xebf8f813UL, 0x2b9898b3UL, 0x22111133UL, + 0xd26969bbUL, 0xa9d9d970UL, 0x078e8e89UL, 0x339494a7UL, + 0x2d9b9bb6UL, 0x3c1e1e22UL, 0x15878792UL, 0xc9e9e920UL, + 0x87cece49UL, 0xaa5555ffUL, 0x50282878UL, 0xa5dfdf7aUL, + 0x038c8c8fUL, 0x59a1a1f8UL, 0x09898980UL, 0x1a0d0d17UL, + 0x65bfbfdaUL, 0xd7e6e631UL, 0x844242c6UL, 0xd06868b8UL, + 0x824141c3UL, 0x299999b0UL, 0x5a2d2d77UL, 0x1e0f0f11UL, + 0x7bb0b0cbUL, 0xa85454fcUL, 0x6dbbbbd6UL, 0x2c16163aUL, +}; + +#ifndef PELI_TAB +static const ulong32 Te4[256] = { + 0x63636363UL, 0x7c7c7c7cUL, 0x77777777UL, 0x7b7b7b7bUL, + 0xf2f2f2f2UL, 0x6b6b6b6bUL, 0x6f6f6f6fUL, 0xc5c5c5c5UL, + 0x30303030UL, 0x01010101UL, 0x67676767UL, 0x2b2b2b2bUL, + 0xfefefefeUL, 0xd7d7d7d7UL, 0xababababUL, 0x76767676UL, + 0xcacacacaUL, 0x82828282UL, 0xc9c9c9c9UL, 0x7d7d7d7dUL, + 0xfafafafaUL, 0x59595959UL, 0x47474747UL, 0xf0f0f0f0UL, + 0xadadadadUL, 0xd4d4d4d4UL, 0xa2a2a2a2UL, 0xafafafafUL, + 0x9c9c9c9cUL, 0xa4a4a4a4UL, 0x72727272UL, 0xc0c0c0c0UL, + 0xb7b7b7b7UL, 0xfdfdfdfdUL, 0x93939393UL, 0x26262626UL, + 0x36363636UL, 0x3f3f3f3fUL, 0xf7f7f7f7UL, 0xccccccccUL, + 0x34343434UL, 0xa5a5a5a5UL, 0xe5e5e5e5UL, 0xf1f1f1f1UL, + 0x71717171UL, 0xd8d8d8d8UL, 0x31313131UL, 0x15151515UL, + 0x04040404UL, 0xc7c7c7c7UL, 0x23232323UL, 0xc3c3c3c3UL, + 0x18181818UL, 0x96969696UL, 0x05050505UL, 0x9a9a9a9aUL, + 0x07070707UL, 0x12121212UL, 0x80808080UL, 0xe2e2e2e2UL, + 0xebebebebUL, 0x27272727UL, 0xb2b2b2b2UL, 0x75757575UL, + 0x09090909UL, 0x83838383UL, 0x2c2c2c2cUL, 0x1a1a1a1aUL, + 0x1b1b1b1bUL, 0x6e6e6e6eUL, 0x5a5a5a5aUL, 0xa0a0a0a0UL, + 0x52525252UL, 0x3b3b3b3bUL, 0xd6d6d6d6UL, 0xb3b3b3b3UL, + 0x29292929UL, 0xe3e3e3e3UL, 0x2f2f2f2fUL, 0x84848484UL, + 0x53535353UL, 0xd1d1d1d1UL, 0x00000000UL, 0xededededUL, + 0x20202020UL, 0xfcfcfcfcUL, 0xb1b1b1b1UL, 0x5b5b5b5bUL, + 0x6a6a6a6aUL, 0xcbcbcbcbUL, 0xbebebebeUL, 0x39393939UL, + 0x4a4a4a4aUL, 0x4c4c4c4cUL, 0x58585858UL, 0xcfcfcfcfUL, + 0xd0d0d0d0UL, 0xefefefefUL, 0xaaaaaaaaUL, 0xfbfbfbfbUL, + 0x43434343UL, 0x4d4d4d4dUL, 0x33333333UL, 0x85858585UL, + 0x45454545UL, 0xf9f9f9f9UL, 0x02020202UL, 0x7f7f7f7fUL, + 0x50505050UL, 0x3c3c3c3cUL, 0x9f9f9f9fUL, 0xa8a8a8a8UL, + 0x51515151UL, 0xa3a3a3a3UL, 0x40404040UL, 0x8f8f8f8fUL, + 0x92929292UL, 0x9d9d9d9dUL, 0x38383838UL, 0xf5f5f5f5UL, + 0xbcbcbcbcUL, 0xb6b6b6b6UL, 0xdadadadaUL, 0x21212121UL, + 0x10101010UL, 0xffffffffUL, 0xf3f3f3f3UL, 0xd2d2d2d2UL, + 0xcdcdcdcdUL, 0x0c0c0c0cUL, 0x13131313UL, 0xececececUL, + 0x5f5f5f5fUL, 0x97979797UL, 0x44444444UL, 0x17171717UL, + 0xc4c4c4c4UL, 0xa7a7a7a7UL, 0x7e7e7e7eUL, 0x3d3d3d3dUL, + 0x64646464UL, 0x5d5d5d5dUL, 0x19191919UL, 0x73737373UL, + 0x60606060UL, 0x81818181UL, 0x4f4f4f4fUL, 0xdcdcdcdcUL, + 0x22222222UL, 0x2a2a2a2aUL, 0x90909090UL, 0x88888888UL, + 0x46464646UL, 0xeeeeeeeeUL, 0xb8b8b8b8UL, 0x14141414UL, + 0xdedededeUL, 0x5e5e5e5eUL, 0x0b0b0b0bUL, 0xdbdbdbdbUL, + 0xe0e0e0e0UL, 0x32323232UL, 0x3a3a3a3aUL, 0x0a0a0a0aUL, + 0x49494949UL, 0x06060606UL, 0x24242424UL, 0x5c5c5c5cUL, + 0xc2c2c2c2UL, 0xd3d3d3d3UL, 0xacacacacUL, 0x62626262UL, + 0x91919191UL, 0x95959595UL, 0xe4e4e4e4UL, 0x79797979UL, + 0xe7e7e7e7UL, 0xc8c8c8c8UL, 0x37373737UL, 0x6d6d6d6dUL, + 0x8d8d8d8dUL, 0xd5d5d5d5UL, 0x4e4e4e4eUL, 0xa9a9a9a9UL, + 0x6c6c6c6cUL, 0x56565656UL, 0xf4f4f4f4UL, 0xeaeaeaeaUL, + 0x65656565UL, 0x7a7a7a7aUL, 0xaeaeaeaeUL, 0x08080808UL, + 0xbabababaUL, 0x78787878UL, 0x25252525UL, 0x2e2e2e2eUL, + 0x1c1c1c1cUL, 0xa6a6a6a6UL, 0xb4b4b4b4UL, 0xc6c6c6c6UL, + 0xe8e8e8e8UL, 0xddddddddUL, 0x74747474UL, 0x1f1f1f1fUL, + 0x4b4b4b4bUL, 0xbdbdbdbdUL, 0x8b8b8b8bUL, 0x8a8a8a8aUL, + 0x70707070UL, 0x3e3e3e3eUL, 0xb5b5b5b5UL, 0x66666666UL, + 0x48484848UL, 0x03030303UL, 0xf6f6f6f6UL, 0x0e0e0e0eUL, + 0x61616161UL, 0x35353535UL, 0x57575757UL, 0xb9b9b9b9UL, + 0x86868686UL, 0xc1c1c1c1UL, 0x1d1d1d1dUL, 0x9e9e9e9eUL, + 0xe1e1e1e1UL, 0xf8f8f8f8UL, 0x98989898UL, 0x11111111UL, + 0x69696969UL, 0xd9d9d9d9UL, 0x8e8e8e8eUL, 0x94949494UL, + 0x9b9b9b9bUL, 0x1e1e1e1eUL, 0x87878787UL, 0xe9e9e9e9UL, + 0xcecececeUL, 0x55555555UL, 0x28282828UL, 0xdfdfdfdfUL, + 0x8c8c8c8cUL, 0xa1a1a1a1UL, 0x89898989UL, 0x0d0d0d0dUL, + 0xbfbfbfbfUL, 0xe6e6e6e6UL, 0x42424242UL, 0x68686868UL, + 0x41414141UL, 0x99999999UL, 0x2d2d2d2dUL, 0x0f0f0f0fUL, + 0xb0b0b0b0UL, 0x54545454UL, 0xbbbbbbbbUL, 0x16161616UL, +}; +#endif + +#ifndef ENCRYPT_ONLY + +static const ulong32 TD0[256] = { + 0x51f4a750UL, 0x7e416553UL, 0x1a17a4c3UL, 0x3a275e96UL, + 0x3bab6bcbUL, 0x1f9d45f1UL, 0xacfa58abUL, 0x4be30393UL, + 0x2030fa55UL, 0xad766df6UL, 0x88cc7691UL, 0xf5024c25UL, + 0x4fe5d7fcUL, 0xc52acbd7UL, 0x26354480UL, 0xb562a38fUL, + 0xdeb15a49UL, 0x25ba1b67UL, 0x45ea0e98UL, 0x5dfec0e1UL, + 0xc32f7502UL, 0x814cf012UL, 0x8d4697a3UL, 0x6bd3f9c6UL, + 0x038f5fe7UL, 0x15929c95UL, 0xbf6d7aebUL, 0x955259daUL, + 0xd4be832dUL, 0x587421d3UL, 0x49e06929UL, 0x8ec9c844UL, + 0x75c2896aUL, 0xf48e7978UL, 0x99583e6bUL, 0x27b971ddUL, + 0xbee14fb6UL, 0xf088ad17UL, 0xc920ac66UL, 0x7dce3ab4UL, + 0x63df4a18UL, 0xe51a3182UL, 0x97513360UL, 0x62537f45UL, + 0xb16477e0UL, 0xbb6bae84UL, 0xfe81a01cUL, 0xf9082b94UL, + 0x70486858UL, 0x8f45fd19UL, 0x94de6c87UL, 0x527bf8b7UL, + 0xab73d323UL, 0x724b02e2UL, 0xe31f8f57UL, 0x6655ab2aUL, + 0xb2eb2807UL, 0x2fb5c203UL, 0x86c57b9aUL, 0xd33708a5UL, + 0x302887f2UL, 0x23bfa5b2UL, 0x02036abaUL, 0xed16825cUL, + 0x8acf1c2bUL, 0xa779b492UL, 0xf307f2f0UL, 0x4e69e2a1UL, + 0x65daf4cdUL, 0x0605bed5UL, 0xd134621fUL, 0xc4a6fe8aUL, + 0x342e539dUL, 0xa2f355a0UL, 0x058ae132UL, 0xa4f6eb75UL, + 0x0b83ec39UL, 0x4060efaaUL, 0x5e719f06UL, 0xbd6e1051UL, + 0x3e218af9UL, 0x96dd063dUL, 0xdd3e05aeUL, 0x4de6bd46UL, + 0x91548db5UL, 0x71c45d05UL, 0x0406d46fUL, 0x605015ffUL, + 0x1998fb24UL, 0xd6bde997UL, 0x894043ccUL, 0x67d99e77UL, + 0xb0e842bdUL, 0x07898b88UL, 0xe7195b38UL, 0x79c8eedbUL, + 0xa17c0a47UL, 0x7c420fe9UL, 0xf8841ec9UL, 0x00000000UL, + 0x09808683UL, 0x322bed48UL, 0x1e1170acUL, 0x6c5a724eUL, + 0xfd0efffbUL, 0x0f853856UL, 0x3daed51eUL, 0x362d3927UL, + 0x0a0fd964UL, 0x685ca621UL, 0x9b5b54d1UL, 0x24362e3aUL, + 0x0c0a67b1UL, 0x9357e70fUL, 0xb4ee96d2UL, 0x1b9b919eUL, + 0x80c0c54fUL, 0x61dc20a2UL, 0x5a774b69UL, 0x1c121a16UL, + 0xe293ba0aUL, 0xc0a02ae5UL, 0x3c22e043UL, 0x121b171dUL, + 0x0e090d0bUL, 0xf28bc7adUL, 0x2db6a8b9UL, 0x141ea9c8UL, + 0x57f11985UL, 0xaf75074cUL, 0xee99ddbbUL, 0xa37f60fdUL, + 0xf701269fUL, 0x5c72f5bcUL, 0x44663bc5UL, 0x5bfb7e34UL, + 0x8b432976UL, 0xcb23c6dcUL, 0xb6edfc68UL, 0xb8e4f163UL, + 0xd731dccaUL, 0x42638510UL, 0x13972240UL, 0x84c61120UL, + 0x854a247dUL, 0xd2bb3df8UL, 0xaef93211UL, 0xc729a16dUL, + 0x1d9e2f4bUL, 0xdcb230f3UL, 0x0d8652ecUL, 0x77c1e3d0UL, + 0x2bb3166cUL, 0xa970b999UL, 0x119448faUL, 0x47e96422UL, + 0xa8fc8cc4UL, 0xa0f03f1aUL, 0x567d2cd8UL, 0x223390efUL, + 0x87494ec7UL, 0xd938d1c1UL, 0x8ccaa2feUL, 0x98d40b36UL, + 0xa6f581cfUL, 0xa57ade28UL, 0xdab78e26UL, 0x3fadbfa4UL, + 0x2c3a9de4UL, 0x5078920dUL, 0x6a5fcc9bUL, 0x547e4662UL, + 0xf68d13c2UL, 0x90d8b8e8UL, 0x2e39f75eUL, 0x82c3aff5UL, + 0x9f5d80beUL, 0x69d0937cUL, 0x6fd52da9UL, 0xcf2512b3UL, + 0xc8ac993bUL, 0x10187da7UL, 0xe89c636eUL, 0xdb3bbb7bUL, + 0xcd267809UL, 0x6e5918f4UL, 0xec9ab701UL, 0x834f9aa8UL, + 0xe6956e65UL, 0xaaffe67eUL, 0x21bccf08UL, 0xef15e8e6UL, + 0xbae79bd9UL, 0x4a6f36ceUL, 0xea9f09d4UL, 0x29b07cd6UL, + 0x31a4b2afUL, 0x2a3f2331UL, 0xc6a59430UL, 0x35a266c0UL, + 0x744ebc37UL, 0xfc82caa6UL, 0xe090d0b0UL, 0x33a7d815UL, + 0xf104984aUL, 0x41ecdaf7UL, 0x7fcd500eUL, 0x1791f62fUL, + 0x764dd68dUL, 0x43efb04dUL, 0xccaa4d54UL, 0xe49604dfUL, + 0x9ed1b5e3UL, 0x4c6a881bUL, 0xc12c1fb8UL, 0x4665517fUL, + 0x9d5eea04UL, 0x018c355dUL, 0xfa877473UL, 0xfb0b412eUL, + 0xb3671d5aUL, 0x92dbd252UL, 0xe9105633UL, 0x6dd64713UL, + 0x9ad7618cUL, 0x37a10c7aUL, 0x59f8148eUL, 0xeb133c89UL, + 0xcea927eeUL, 0xb761c935UL, 0xe11ce5edUL, 0x7a47b13cUL, + 0x9cd2df59UL, 0x55f2733fUL, 0x1814ce79UL, 0x73c737bfUL, + 0x53f7cdeaUL, 0x5ffdaa5bUL, 0xdf3d6f14UL, 0x7844db86UL, + 0xcaaff381UL, 0xb968c43eUL, 0x3824342cUL, 0xc2a3405fUL, + 0x161dc372UL, 0xbce2250cUL, 0x283c498bUL, 0xff0d9541UL, + 0x39a80171UL, 0x080cb3deUL, 0xd8b4e49cUL, 0x6456c190UL, + 0x7bcb8461UL, 0xd532b670UL, 0x486c5c74UL, 0xd0b85742UL, +}; + +static const ulong32 Td4[256] = { + 0x52525252UL, 0x09090909UL, 0x6a6a6a6aUL, 0xd5d5d5d5UL, + 0x30303030UL, 0x36363636UL, 0xa5a5a5a5UL, 0x38383838UL, + 0xbfbfbfbfUL, 0x40404040UL, 0xa3a3a3a3UL, 0x9e9e9e9eUL, + 0x81818181UL, 0xf3f3f3f3UL, 0xd7d7d7d7UL, 0xfbfbfbfbUL, + 0x7c7c7c7cUL, 0xe3e3e3e3UL, 0x39393939UL, 0x82828282UL, + 0x9b9b9b9bUL, 0x2f2f2f2fUL, 0xffffffffUL, 0x87878787UL, + 0x34343434UL, 0x8e8e8e8eUL, 0x43434343UL, 0x44444444UL, + 0xc4c4c4c4UL, 0xdedededeUL, 0xe9e9e9e9UL, 0xcbcbcbcbUL, + 0x54545454UL, 0x7b7b7b7bUL, 0x94949494UL, 0x32323232UL, + 0xa6a6a6a6UL, 0xc2c2c2c2UL, 0x23232323UL, 0x3d3d3d3dUL, + 0xeeeeeeeeUL, 0x4c4c4c4cUL, 0x95959595UL, 0x0b0b0b0bUL, + 0x42424242UL, 0xfafafafaUL, 0xc3c3c3c3UL, 0x4e4e4e4eUL, + 0x08080808UL, 0x2e2e2e2eUL, 0xa1a1a1a1UL, 0x66666666UL, + 0x28282828UL, 0xd9d9d9d9UL, 0x24242424UL, 0xb2b2b2b2UL, + 0x76767676UL, 0x5b5b5b5bUL, 0xa2a2a2a2UL, 0x49494949UL, + 0x6d6d6d6dUL, 0x8b8b8b8bUL, 0xd1d1d1d1UL, 0x25252525UL, + 0x72727272UL, 0xf8f8f8f8UL, 0xf6f6f6f6UL, 0x64646464UL, + 0x86868686UL, 0x68686868UL, 0x98989898UL, 0x16161616UL, + 0xd4d4d4d4UL, 0xa4a4a4a4UL, 0x5c5c5c5cUL, 0xccccccccUL, + 0x5d5d5d5dUL, 0x65656565UL, 0xb6b6b6b6UL, 0x92929292UL, + 0x6c6c6c6cUL, 0x70707070UL, 0x48484848UL, 0x50505050UL, + 0xfdfdfdfdUL, 0xededededUL, 0xb9b9b9b9UL, 0xdadadadaUL, + 0x5e5e5e5eUL, 0x15151515UL, 0x46464646UL, 0x57575757UL, + 0xa7a7a7a7UL, 0x8d8d8d8dUL, 0x9d9d9d9dUL, 0x84848484UL, + 0x90909090UL, 0xd8d8d8d8UL, 0xababababUL, 0x00000000UL, + 0x8c8c8c8cUL, 0xbcbcbcbcUL, 0xd3d3d3d3UL, 0x0a0a0a0aUL, + 0xf7f7f7f7UL, 0xe4e4e4e4UL, 0x58585858UL, 0x05050505UL, + 0xb8b8b8b8UL, 0xb3b3b3b3UL, 0x45454545UL, 0x06060606UL, + 0xd0d0d0d0UL, 0x2c2c2c2cUL, 0x1e1e1e1eUL, 0x8f8f8f8fUL, + 0xcacacacaUL, 0x3f3f3f3fUL, 0x0f0f0f0fUL, 0x02020202UL, + 0xc1c1c1c1UL, 0xafafafafUL, 0xbdbdbdbdUL, 0x03030303UL, + 0x01010101UL, 0x13131313UL, 0x8a8a8a8aUL, 0x6b6b6b6bUL, + 0x3a3a3a3aUL, 0x91919191UL, 0x11111111UL, 0x41414141UL, + 0x4f4f4f4fUL, 0x67676767UL, 0xdcdcdcdcUL, 0xeaeaeaeaUL, + 0x97979797UL, 0xf2f2f2f2UL, 0xcfcfcfcfUL, 0xcecececeUL, + 0xf0f0f0f0UL, 0xb4b4b4b4UL, 0xe6e6e6e6UL, 0x73737373UL, + 0x96969696UL, 0xacacacacUL, 0x74747474UL, 0x22222222UL, + 0xe7e7e7e7UL, 0xadadadadUL, 0x35353535UL, 0x85858585UL, + 0xe2e2e2e2UL, 0xf9f9f9f9UL, 0x37373737UL, 0xe8e8e8e8UL, + 0x1c1c1c1cUL, 0x75757575UL, 0xdfdfdfdfUL, 0x6e6e6e6eUL, + 0x47474747UL, 0xf1f1f1f1UL, 0x1a1a1a1aUL, 0x71717171UL, + 0x1d1d1d1dUL, 0x29292929UL, 0xc5c5c5c5UL, 0x89898989UL, + 0x6f6f6f6fUL, 0xb7b7b7b7UL, 0x62626262UL, 0x0e0e0e0eUL, + 0xaaaaaaaaUL, 0x18181818UL, 0xbebebebeUL, 0x1b1b1b1bUL, + 0xfcfcfcfcUL, 0x56565656UL, 0x3e3e3e3eUL, 0x4b4b4b4bUL, + 0xc6c6c6c6UL, 0xd2d2d2d2UL, 0x79797979UL, 0x20202020UL, + 0x9a9a9a9aUL, 0xdbdbdbdbUL, 0xc0c0c0c0UL, 0xfefefefeUL, + 0x78787878UL, 0xcdcdcdcdUL, 0x5a5a5a5aUL, 0xf4f4f4f4UL, + 0x1f1f1f1fUL, 0xddddddddUL, 0xa8a8a8a8UL, 0x33333333UL, + 0x88888888UL, 0x07070707UL, 0xc7c7c7c7UL, 0x31313131UL, + 0xb1b1b1b1UL, 0x12121212UL, 0x10101010UL, 0x59595959UL, + 0x27272727UL, 0x80808080UL, 0xececececUL, 0x5f5f5f5fUL, + 0x60606060UL, 0x51515151UL, 0x7f7f7f7fUL, 0xa9a9a9a9UL, + 0x19191919UL, 0xb5b5b5b5UL, 0x4a4a4a4aUL, 0x0d0d0d0dUL, + 0x2d2d2d2dUL, 0xe5e5e5e5UL, 0x7a7a7a7aUL, 0x9f9f9f9fUL, + 0x93939393UL, 0xc9c9c9c9UL, 0x9c9c9c9cUL, 0xefefefefUL, + 0xa0a0a0a0UL, 0xe0e0e0e0UL, 0x3b3b3b3bUL, 0x4d4d4d4dUL, + 0xaeaeaeaeUL, 0x2a2a2a2aUL, 0xf5f5f5f5UL, 0xb0b0b0b0UL, + 0xc8c8c8c8UL, 0xebebebebUL, 0xbbbbbbbbUL, 0x3c3c3c3cUL, + 0x83838383UL, 0x53535353UL, 0x99999999UL, 0x61616161UL, + 0x17171717UL, 0x2b2b2b2bUL, 0x04040404UL, 0x7e7e7e7eUL, + 0xbabababaUL, 0x77777777UL, 0xd6d6d6d6UL, 0x26262626UL, + 0xe1e1e1e1UL, 0x69696969UL, 0x14141414UL, 0x63636363UL, + 0x55555555UL, 0x21212121UL, 0x0c0c0c0cUL, 0x7d7d7d7dUL, +}; + +#endif /* ENCRYPT_ONLY */ + +#ifdef LTC_SMALL_CODE + +#define Te0(x) TE0[x] +#define Te1(x) RORc(TE0[x], 8) +#define Te2(x) RORc(TE0[x], 16) +#define Te3(x) RORc(TE0[x], 24) + +#define Td0(x) TD0[x] +#define Td1(x) RORc(TD0[x], 8) +#define Td2(x) RORc(TD0[x], 16) +#define Td3(x) RORc(TD0[x], 24) + +#define Te4_0 0x000000FF & Te4 +#define Te4_1 0x0000FF00 & Te4 +#define Te4_2 0x00FF0000 & Te4 +#define Te4_3 0xFF000000 & Te4 + +#else + +#define Te0(x) TE0[x] +#define Te1(x) TE1[x] +#define Te2(x) TE2[x] +#define Te3(x) TE3[x] + +#define Td0(x) TD0[x] +#define Td1(x) TD1[x] +#define Td2(x) TD2[x] +#define Td3(x) TD3[x] + +static const ulong32 TE1[256] = { + 0xa5c66363UL, 0x84f87c7cUL, 0x99ee7777UL, 0x8df67b7bUL, + 0x0dfff2f2UL, 0xbdd66b6bUL, 0xb1de6f6fUL, 0x5491c5c5UL, + 0x50603030UL, 0x03020101UL, 0xa9ce6767UL, 0x7d562b2bUL, + 0x19e7fefeUL, 0x62b5d7d7UL, 0xe64dababUL, 0x9aec7676UL, + 0x458fcacaUL, 0x9d1f8282UL, 0x4089c9c9UL, 0x87fa7d7dUL, + 0x15effafaUL, 0xebb25959UL, 0xc98e4747UL, 0x0bfbf0f0UL, + 0xec41adadUL, 0x67b3d4d4UL, 0xfd5fa2a2UL, 0xea45afafUL, + 0xbf239c9cUL, 0xf753a4a4UL, 0x96e47272UL, 0x5b9bc0c0UL, + 0xc275b7b7UL, 0x1ce1fdfdUL, 0xae3d9393UL, 0x6a4c2626UL, + 0x5a6c3636UL, 0x417e3f3fUL, 0x02f5f7f7UL, 0x4f83ccccUL, + 0x5c683434UL, 0xf451a5a5UL, 0x34d1e5e5UL, 0x08f9f1f1UL, + 0x93e27171UL, 0x73abd8d8UL, 0x53623131UL, 0x3f2a1515UL, + 0x0c080404UL, 0x5295c7c7UL, 0x65462323UL, 0x5e9dc3c3UL, + 0x28301818UL, 0xa1379696UL, 0x0f0a0505UL, 0xb52f9a9aUL, + 0x090e0707UL, 0x36241212UL, 0x9b1b8080UL, 0x3ddfe2e2UL, + 0x26cdebebUL, 0x694e2727UL, 0xcd7fb2b2UL, 0x9fea7575UL, + 0x1b120909UL, 0x9e1d8383UL, 0x74582c2cUL, 0x2e341a1aUL, + 0x2d361b1bUL, 0xb2dc6e6eUL, 0xeeb45a5aUL, 0xfb5ba0a0UL, + 0xf6a45252UL, 0x4d763b3bUL, 0x61b7d6d6UL, 0xce7db3b3UL, + 0x7b522929UL, 0x3edde3e3UL, 0x715e2f2fUL, 0x97138484UL, + 0xf5a65353UL, 0x68b9d1d1UL, 0x00000000UL, 0x2cc1ededUL, + 0x60402020UL, 0x1fe3fcfcUL, 0xc879b1b1UL, 0xedb65b5bUL, + 0xbed46a6aUL, 0x468dcbcbUL, 0xd967bebeUL, 0x4b723939UL, + 0xde944a4aUL, 0xd4984c4cUL, 0xe8b05858UL, 0x4a85cfcfUL, + 0x6bbbd0d0UL, 0x2ac5efefUL, 0xe54faaaaUL, 0x16edfbfbUL, + 0xc5864343UL, 0xd79a4d4dUL, 0x55663333UL, 0x94118585UL, + 0xcf8a4545UL, 0x10e9f9f9UL, 0x06040202UL, 0x81fe7f7fUL, + 0xf0a05050UL, 0x44783c3cUL, 0xba259f9fUL, 0xe34ba8a8UL, + 0xf3a25151UL, 0xfe5da3a3UL, 0xc0804040UL, 0x8a058f8fUL, + 0xad3f9292UL, 0xbc219d9dUL, 0x48703838UL, 0x04f1f5f5UL, + 0xdf63bcbcUL, 0xc177b6b6UL, 0x75afdadaUL, 0x63422121UL, + 0x30201010UL, 0x1ae5ffffUL, 0x0efdf3f3UL, 0x6dbfd2d2UL, + 0x4c81cdcdUL, 0x14180c0cUL, 0x35261313UL, 0x2fc3ececUL, + 0xe1be5f5fUL, 0xa2359797UL, 0xcc884444UL, 0x392e1717UL, + 0x5793c4c4UL, 0xf255a7a7UL, 0x82fc7e7eUL, 0x477a3d3dUL, + 0xacc86464UL, 0xe7ba5d5dUL, 0x2b321919UL, 0x95e67373UL, + 0xa0c06060UL, 0x98198181UL, 0xd19e4f4fUL, 0x7fa3dcdcUL, + 0x66442222UL, 0x7e542a2aUL, 0xab3b9090UL, 0x830b8888UL, + 0xca8c4646UL, 0x29c7eeeeUL, 0xd36bb8b8UL, 0x3c281414UL, + 0x79a7dedeUL, 0xe2bc5e5eUL, 0x1d160b0bUL, 0x76addbdbUL, + 0x3bdbe0e0UL, 0x56643232UL, 0x4e743a3aUL, 0x1e140a0aUL, + 0xdb924949UL, 0x0a0c0606UL, 0x6c482424UL, 0xe4b85c5cUL, + 0x5d9fc2c2UL, 0x6ebdd3d3UL, 0xef43acacUL, 0xa6c46262UL, + 0xa8399191UL, 0xa4319595UL, 0x37d3e4e4UL, 0x8bf27979UL, + 0x32d5e7e7UL, 0x438bc8c8UL, 0x596e3737UL, 0xb7da6d6dUL, + 0x8c018d8dUL, 0x64b1d5d5UL, 0xd29c4e4eUL, 0xe049a9a9UL, + 0xb4d86c6cUL, 0xfaac5656UL, 0x07f3f4f4UL, 0x25cfeaeaUL, + 0xafca6565UL, 0x8ef47a7aUL, 0xe947aeaeUL, 0x18100808UL, + 0xd56fbabaUL, 0x88f07878UL, 0x6f4a2525UL, 0x725c2e2eUL, + 0x24381c1cUL, 0xf157a6a6UL, 0xc773b4b4UL, 0x5197c6c6UL, + 0x23cbe8e8UL, 0x7ca1ddddUL, 0x9ce87474UL, 0x213e1f1fUL, + 0xdd964b4bUL, 0xdc61bdbdUL, 0x860d8b8bUL, 0x850f8a8aUL, + 0x90e07070UL, 0x427c3e3eUL, 0xc471b5b5UL, 0xaacc6666UL, + 0xd8904848UL, 0x05060303UL, 0x01f7f6f6UL, 0x121c0e0eUL, + 0xa3c26161UL, 0x5f6a3535UL, 0xf9ae5757UL, 0xd069b9b9UL, + 0x91178686UL, 0x5899c1c1UL, 0x273a1d1dUL, 0xb9279e9eUL, + 0x38d9e1e1UL, 0x13ebf8f8UL, 0xb32b9898UL, 0x33221111UL, + 0xbbd26969UL, 0x70a9d9d9UL, 0x89078e8eUL, 0xa7339494UL, + 0xb62d9b9bUL, 0x223c1e1eUL, 0x92158787UL, 0x20c9e9e9UL, + 0x4987ceceUL, 0xffaa5555UL, 0x78502828UL, 0x7aa5dfdfUL, + 0x8f038c8cUL, 0xf859a1a1UL, 0x80098989UL, 0x171a0d0dUL, + 0xda65bfbfUL, 0x31d7e6e6UL, 0xc6844242UL, 0xb8d06868UL, + 0xc3824141UL, 0xb0299999UL, 0x775a2d2dUL, 0x111e0f0fUL, + 0xcb7bb0b0UL, 0xfca85454UL, 0xd66dbbbbUL, 0x3a2c1616UL, +}; +static const ulong32 TE2[256] = { + 0x63a5c663UL, 0x7c84f87cUL, 0x7799ee77UL, 0x7b8df67bUL, + 0xf20dfff2UL, 0x6bbdd66bUL, 0x6fb1de6fUL, 0xc55491c5UL, + 0x30506030UL, 0x01030201UL, 0x67a9ce67UL, 0x2b7d562bUL, + 0xfe19e7feUL, 0xd762b5d7UL, 0xabe64dabUL, 0x769aec76UL, + 0xca458fcaUL, 0x829d1f82UL, 0xc94089c9UL, 0x7d87fa7dUL, + 0xfa15effaUL, 0x59ebb259UL, 0x47c98e47UL, 0xf00bfbf0UL, + 0xadec41adUL, 0xd467b3d4UL, 0xa2fd5fa2UL, 0xafea45afUL, + 0x9cbf239cUL, 0xa4f753a4UL, 0x7296e472UL, 0xc05b9bc0UL, + 0xb7c275b7UL, 0xfd1ce1fdUL, 0x93ae3d93UL, 0x266a4c26UL, + 0x365a6c36UL, 0x3f417e3fUL, 0xf702f5f7UL, 0xcc4f83ccUL, + 0x345c6834UL, 0xa5f451a5UL, 0xe534d1e5UL, 0xf108f9f1UL, + 0x7193e271UL, 0xd873abd8UL, 0x31536231UL, 0x153f2a15UL, + 0x040c0804UL, 0xc75295c7UL, 0x23654623UL, 0xc35e9dc3UL, + 0x18283018UL, 0x96a13796UL, 0x050f0a05UL, 0x9ab52f9aUL, + 0x07090e07UL, 0x12362412UL, 0x809b1b80UL, 0xe23ddfe2UL, + 0xeb26cdebUL, 0x27694e27UL, 0xb2cd7fb2UL, 0x759fea75UL, + 0x091b1209UL, 0x839e1d83UL, 0x2c74582cUL, 0x1a2e341aUL, + 0x1b2d361bUL, 0x6eb2dc6eUL, 0x5aeeb45aUL, 0xa0fb5ba0UL, + 0x52f6a452UL, 0x3b4d763bUL, 0xd661b7d6UL, 0xb3ce7db3UL, + 0x297b5229UL, 0xe33edde3UL, 0x2f715e2fUL, 0x84971384UL, + 0x53f5a653UL, 0xd168b9d1UL, 0x00000000UL, 0xed2cc1edUL, + 0x20604020UL, 0xfc1fe3fcUL, 0xb1c879b1UL, 0x5bedb65bUL, + 0x6abed46aUL, 0xcb468dcbUL, 0xbed967beUL, 0x394b7239UL, + 0x4ade944aUL, 0x4cd4984cUL, 0x58e8b058UL, 0xcf4a85cfUL, + 0xd06bbbd0UL, 0xef2ac5efUL, 0xaae54faaUL, 0xfb16edfbUL, + 0x43c58643UL, 0x4dd79a4dUL, 0x33556633UL, 0x85941185UL, + 0x45cf8a45UL, 0xf910e9f9UL, 0x02060402UL, 0x7f81fe7fUL, + 0x50f0a050UL, 0x3c44783cUL, 0x9fba259fUL, 0xa8e34ba8UL, + 0x51f3a251UL, 0xa3fe5da3UL, 0x40c08040UL, 0x8f8a058fUL, + 0x92ad3f92UL, 0x9dbc219dUL, 0x38487038UL, 0xf504f1f5UL, + 0xbcdf63bcUL, 0xb6c177b6UL, 0xda75afdaUL, 0x21634221UL, + 0x10302010UL, 0xff1ae5ffUL, 0xf30efdf3UL, 0xd26dbfd2UL, + 0xcd4c81cdUL, 0x0c14180cUL, 0x13352613UL, 0xec2fc3ecUL, + 0x5fe1be5fUL, 0x97a23597UL, 0x44cc8844UL, 0x17392e17UL, + 0xc45793c4UL, 0xa7f255a7UL, 0x7e82fc7eUL, 0x3d477a3dUL, + 0x64acc864UL, 0x5de7ba5dUL, 0x192b3219UL, 0x7395e673UL, + 0x60a0c060UL, 0x81981981UL, 0x4fd19e4fUL, 0xdc7fa3dcUL, + 0x22664422UL, 0x2a7e542aUL, 0x90ab3b90UL, 0x88830b88UL, + 0x46ca8c46UL, 0xee29c7eeUL, 0xb8d36bb8UL, 0x143c2814UL, + 0xde79a7deUL, 0x5ee2bc5eUL, 0x0b1d160bUL, 0xdb76addbUL, + 0xe03bdbe0UL, 0x32566432UL, 0x3a4e743aUL, 0x0a1e140aUL, + 0x49db9249UL, 0x060a0c06UL, 0x246c4824UL, 0x5ce4b85cUL, + 0xc25d9fc2UL, 0xd36ebdd3UL, 0xacef43acUL, 0x62a6c462UL, + 0x91a83991UL, 0x95a43195UL, 0xe437d3e4UL, 0x798bf279UL, + 0xe732d5e7UL, 0xc8438bc8UL, 0x37596e37UL, 0x6db7da6dUL, + 0x8d8c018dUL, 0xd564b1d5UL, 0x4ed29c4eUL, 0xa9e049a9UL, + 0x6cb4d86cUL, 0x56faac56UL, 0xf407f3f4UL, 0xea25cfeaUL, + 0x65afca65UL, 0x7a8ef47aUL, 0xaee947aeUL, 0x08181008UL, + 0xbad56fbaUL, 0x7888f078UL, 0x256f4a25UL, 0x2e725c2eUL, + 0x1c24381cUL, 0xa6f157a6UL, 0xb4c773b4UL, 0xc65197c6UL, + 0xe823cbe8UL, 0xdd7ca1ddUL, 0x749ce874UL, 0x1f213e1fUL, + 0x4bdd964bUL, 0xbddc61bdUL, 0x8b860d8bUL, 0x8a850f8aUL, + 0x7090e070UL, 0x3e427c3eUL, 0xb5c471b5UL, 0x66aacc66UL, + 0x48d89048UL, 0x03050603UL, 0xf601f7f6UL, 0x0e121c0eUL, + 0x61a3c261UL, 0x355f6a35UL, 0x57f9ae57UL, 0xb9d069b9UL, + 0x86911786UL, 0xc15899c1UL, 0x1d273a1dUL, 0x9eb9279eUL, + 0xe138d9e1UL, 0xf813ebf8UL, 0x98b32b98UL, 0x11332211UL, + 0x69bbd269UL, 0xd970a9d9UL, 0x8e89078eUL, 0x94a73394UL, + 0x9bb62d9bUL, 0x1e223c1eUL, 0x87921587UL, 0xe920c9e9UL, + 0xce4987ceUL, 0x55ffaa55UL, 0x28785028UL, 0xdf7aa5dfUL, + 0x8c8f038cUL, 0xa1f859a1UL, 0x89800989UL, 0x0d171a0dUL, + 0xbfda65bfUL, 0xe631d7e6UL, 0x42c68442UL, 0x68b8d068UL, + 0x41c38241UL, 0x99b02999UL, 0x2d775a2dUL, 0x0f111e0fUL, + 0xb0cb7bb0UL, 0x54fca854UL, 0xbbd66dbbUL, 0x163a2c16UL, +}; +static const ulong32 TE3[256] = { + + 0x6363a5c6UL, 0x7c7c84f8UL, 0x777799eeUL, 0x7b7b8df6UL, + 0xf2f20dffUL, 0x6b6bbdd6UL, 0x6f6fb1deUL, 0xc5c55491UL, + 0x30305060UL, 0x01010302UL, 0x6767a9ceUL, 0x2b2b7d56UL, + 0xfefe19e7UL, 0xd7d762b5UL, 0xababe64dUL, 0x76769aecUL, + 0xcaca458fUL, 0x82829d1fUL, 0xc9c94089UL, 0x7d7d87faUL, + 0xfafa15efUL, 0x5959ebb2UL, 0x4747c98eUL, 0xf0f00bfbUL, + 0xadadec41UL, 0xd4d467b3UL, 0xa2a2fd5fUL, 0xafafea45UL, + 0x9c9cbf23UL, 0xa4a4f753UL, 0x727296e4UL, 0xc0c05b9bUL, + 0xb7b7c275UL, 0xfdfd1ce1UL, 0x9393ae3dUL, 0x26266a4cUL, + 0x36365a6cUL, 0x3f3f417eUL, 0xf7f702f5UL, 0xcccc4f83UL, + 0x34345c68UL, 0xa5a5f451UL, 0xe5e534d1UL, 0xf1f108f9UL, + 0x717193e2UL, 0xd8d873abUL, 0x31315362UL, 0x15153f2aUL, + 0x04040c08UL, 0xc7c75295UL, 0x23236546UL, 0xc3c35e9dUL, + 0x18182830UL, 0x9696a137UL, 0x05050f0aUL, 0x9a9ab52fUL, + 0x0707090eUL, 0x12123624UL, 0x80809b1bUL, 0xe2e23ddfUL, + 0xebeb26cdUL, 0x2727694eUL, 0xb2b2cd7fUL, 0x75759feaUL, + 0x09091b12UL, 0x83839e1dUL, 0x2c2c7458UL, 0x1a1a2e34UL, + 0x1b1b2d36UL, 0x6e6eb2dcUL, 0x5a5aeeb4UL, 0xa0a0fb5bUL, + 0x5252f6a4UL, 0x3b3b4d76UL, 0xd6d661b7UL, 0xb3b3ce7dUL, + 0x29297b52UL, 0xe3e33eddUL, 0x2f2f715eUL, 0x84849713UL, + 0x5353f5a6UL, 0xd1d168b9UL, 0x00000000UL, 0xeded2cc1UL, + 0x20206040UL, 0xfcfc1fe3UL, 0xb1b1c879UL, 0x5b5bedb6UL, + 0x6a6abed4UL, 0xcbcb468dUL, 0xbebed967UL, 0x39394b72UL, + 0x4a4ade94UL, 0x4c4cd498UL, 0x5858e8b0UL, 0xcfcf4a85UL, + 0xd0d06bbbUL, 0xefef2ac5UL, 0xaaaae54fUL, 0xfbfb16edUL, + 0x4343c586UL, 0x4d4dd79aUL, 0x33335566UL, 0x85859411UL, + 0x4545cf8aUL, 0xf9f910e9UL, 0x02020604UL, 0x7f7f81feUL, + 0x5050f0a0UL, 0x3c3c4478UL, 0x9f9fba25UL, 0xa8a8e34bUL, + 0x5151f3a2UL, 0xa3a3fe5dUL, 0x4040c080UL, 0x8f8f8a05UL, + 0x9292ad3fUL, 0x9d9dbc21UL, 0x38384870UL, 0xf5f504f1UL, + 0xbcbcdf63UL, 0xb6b6c177UL, 0xdada75afUL, 0x21216342UL, + 0x10103020UL, 0xffff1ae5UL, 0xf3f30efdUL, 0xd2d26dbfUL, + 0xcdcd4c81UL, 0x0c0c1418UL, 0x13133526UL, 0xecec2fc3UL, + 0x5f5fe1beUL, 0x9797a235UL, 0x4444cc88UL, 0x1717392eUL, + 0xc4c45793UL, 0xa7a7f255UL, 0x7e7e82fcUL, 0x3d3d477aUL, + 0x6464acc8UL, 0x5d5de7baUL, 0x19192b32UL, 0x737395e6UL, + 0x6060a0c0UL, 0x81819819UL, 0x4f4fd19eUL, 0xdcdc7fa3UL, + 0x22226644UL, 0x2a2a7e54UL, 0x9090ab3bUL, 0x8888830bUL, + 0x4646ca8cUL, 0xeeee29c7UL, 0xb8b8d36bUL, 0x14143c28UL, + 0xdede79a7UL, 0x5e5ee2bcUL, 0x0b0b1d16UL, 0xdbdb76adUL, + 0xe0e03bdbUL, 0x32325664UL, 0x3a3a4e74UL, 0x0a0a1e14UL, + 0x4949db92UL, 0x06060a0cUL, 0x24246c48UL, 0x5c5ce4b8UL, + 0xc2c25d9fUL, 0xd3d36ebdUL, 0xacacef43UL, 0x6262a6c4UL, + 0x9191a839UL, 0x9595a431UL, 0xe4e437d3UL, 0x79798bf2UL, + 0xe7e732d5UL, 0xc8c8438bUL, 0x3737596eUL, 0x6d6db7daUL, + 0x8d8d8c01UL, 0xd5d564b1UL, 0x4e4ed29cUL, 0xa9a9e049UL, + 0x6c6cb4d8UL, 0x5656faacUL, 0xf4f407f3UL, 0xeaea25cfUL, + 0x6565afcaUL, 0x7a7a8ef4UL, 0xaeaee947UL, 0x08081810UL, + 0xbabad56fUL, 0x787888f0UL, 0x25256f4aUL, 0x2e2e725cUL, + 0x1c1c2438UL, 0xa6a6f157UL, 0xb4b4c773UL, 0xc6c65197UL, + 0xe8e823cbUL, 0xdddd7ca1UL, 0x74749ce8UL, 0x1f1f213eUL, + 0x4b4bdd96UL, 0xbdbddc61UL, 0x8b8b860dUL, 0x8a8a850fUL, + 0x707090e0UL, 0x3e3e427cUL, 0xb5b5c471UL, 0x6666aaccUL, + 0x4848d890UL, 0x03030506UL, 0xf6f601f7UL, 0x0e0e121cUL, + 0x6161a3c2UL, 0x35355f6aUL, 0x5757f9aeUL, 0xb9b9d069UL, + 0x86869117UL, 0xc1c15899UL, 0x1d1d273aUL, 0x9e9eb927UL, + 0xe1e138d9UL, 0xf8f813ebUL, 0x9898b32bUL, 0x11113322UL, + 0x6969bbd2UL, 0xd9d970a9UL, 0x8e8e8907UL, 0x9494a733UL, + 0x9b9bb62dUL, 0x1e1e223cUL, 0x87879215UL, 0xe9e920c9UL, + 0xcece4987UL, 0x5555ffaaUL, 0x28287850UL, 0xdfdf7aa5UL, + 0x8c8c8f03UL, 0xa1a1f859UL, 0x89898009UL, 0x0d0d171aUL, + 0xbfbfda65UL, 0xe6e631d7UL, 0x4242c684UL, 0x6868b8d0UL, + 0x4141c382UL, 0x9999b029UL, 0x2d2d775aUL, 0x0f0f111eUL, + 0xb0b0cb7bUL, 0x5454fca8UL, 0xbbbbd66dUL, 0x16163a2cUL, +}; + +#ifndef PELI_TAB +static const ulong32 Te4_0[] = { +0x00000063UL, 0x0000007cUL, 0x00000077UL, 0x0000007bUL, 0x000000f2UL, 0x0000006bUL, 0x0000006fUL, 0x000000c5UL, +0x00000030UL, 0x00000001UL, 0x00000067UL, 0x0000002bUL, 0x000000feUL, 0x000000d7UL, 0x000000abUL, 0x00000076UL, +0x000000caUL, 0x00000082UL, 0x000000c9UL, 0x0000007dUL, 0x000000faUL, 0x00000059UL, 0x00000047UL, 0x000000f0UL, +0x000000adUL, 0x000000d4UL, 0x000000a2UL, 0x000000afUL, 0x0000009cUL, 0x000000a4UL, 0x00000072UL, 0x000000c0UL, +0x000000b7UL, 0x000000fdUL, 0x00000093UL, 0x00000026UL, 0x00000036UL, 0x0000003fUL, 0x000000f7UL, 0x000000ccUL, +0x00000034UL, 0x000000a5UL, 0x000000e5UL, 0x000000f1UL, 0x00000071UL, 0x000000d8UL, 0x00000031UL, 0x00000015UL, +0x00000004UL, 0x000000c7UL, 0x00000023UL, 0x000000c3UL, 0x00000018UL, 0x00000096UL, 0x00000005UL, 0x0000009aUL, +0x00000007UL, 0x00000012UL, 0x00000080UL, 0x000000e2UL, 0x000000ebUL, 0x00000027UL, 0x000000b2UL, 0x00000075UL, +0x00000009UL, 0x00000083UL, 0x0000002cUL, 0x0000001aUL, 0x0000001bUL, 0x0000006eUL, 0x0000005aUL, 0x000000a0UL, +0x00000052UL, 0x0000003bUL, 0x000000d6UL, 0x000000b3UL, 0x00000029UL, 0x000000e3UL, 0x0000002fUL, 0x00000084UL, +0x00000053UL, 0x000000d1UL, 0x00000000UL, 0x000000edUL, 0x00000020UL, 0x000000fcUL, 0x000000b1UL, 0x0000005bUL, +0x0000006aUL, 0x000000cbUL, 0x000000beUL, 0x00000039UL, 0x0000004aUL, 0x0000004cUL, 0x00000058UL, 0x000000cfUL, +0x000000d0UL, 0x000000efUL, 0x000000aaUL, 0x000000fbUL, 0x00000043UL, 0x0000004dUL, 0x00000033UL, 0x00000085UL, +0x00000045UL, 0x000000f9UL, 0x00000002UL, 0x0000007fUL, 0x00000050UL, 0x0000003cUL, 0x0000009fUL, 0x000000a8UL, +0x00000051UL, 0x000000a3UL, 0x00000040UL, 0x0000008fUL, 0x00000092UL, 0x0000009dUL, 0x00000038UL, 0x000000f5UL, +0x000000bcUL, 0x000000b6UL, 0x000000daUL, 0x00000021UL, 0x00000010UL, 0x000000ffUL, 0x000000f3UL, 0x000000d2UL, +0x000000cdUL, 0x0000000cUL, 0x00000013UL, 0x000000ecUL, 0x0000005fUL, 0x00000097UL, 0x00000044UL, 0x00000017UL, +0x000000c4UL, 0x000000a7UL, 0x0000007eUL, 0x0000003dUL, 0x00000064UL, 0x0000005dUL, 0x00000019UL, 0x00000073UL, +0x00000060UL, 0x00000081UL, 0x0000004fUL, 0x000000dcUL, 0x00000022UL, 0x0000002aUL, 0x00000090UL, 0x00000088UL, +0x00000046UL, 0x000000eeUL, 0x000000b8UL, 0x00000014UL, 0x000000deUL, 0x0000005eUL, 0x0000000bUL, 0x000000dbUL, +0x000000e0UL, 0x00000032UL, 0x0000003aUL, 0x0000000aUL, 0x00000049UL, 0x00000006UL, 0x00000024UL, 0x0000005cUL, +0x000000c2UL, 0x000000d3UL, 0x000000acUL, 0x00000062UL, 0x00000091UL, 0x00000095UL, 0x000000e4UL, 0x00000079UL, +0x000000e7UL, 0x000000c8UL, 0x00000037UL, 0x0000006dUL, 0x0000008dUL, 0x000000d5UL, 0x0000004eUL, 0x000000a9UL, +0x0000006cUL, 0x00000056UL, 0x000000f4UL, 0x000000eaUL, 0x00000065UL, 0x0000007aUL, 0x000000aeUL, 0x00000008UL, +0x000000baUL, 0x00000078UL, 0x00000025UL, 0x0000002eUL, 0x0000001cUL, 0x000000a6UL, 0x000000b4UL, 0x000000c6UL, +0x000000e8UL, 0x000000ddUL, 0x00000074UL, 0x0000001fUL, 0x0000004bUL, 0x000000bdUL, 0x0000008bUL, 0x0000008aUL, +0x00000070UL, 0x0000003eUL, 0x000000b5UL, 0x00000066UL, 0x00000048UL, 0x00000003UL, 0x000000f6UL, 0x0000000eUL, +0x00000061UL, 0x00000035UL, 0x00000057UL, 0x000000b9UL, 0x00000086UL, 0x000000c1UL, 0x0000001dUL, 0x0000009eUL, +0x000000e1UL, 0x000000f8UL, 0x00000098UL, 0x00000011UL, 0x00000069UL, 0x000000d9UL, 0x0000008eUL, 0x00000094UL, +0x0000009bUL, 0x0000001eUL, 0x00000087UL, 0x000000e9UL, 0x000000ceUL, 0x00000055UL, 0x00000028UL, 0x000000dfUL, +0x0000008cUL, 0x000000a1UL, 0x00000089UL, 0x0000000dUL, 0x000000bfUL, 0x000000e6UL, 0x00000042UL, 0x00000068UL, +0x00000041UL, 0x00000099UL, 0x0000002dUL, 0x0000000fUL, 0x000000b0UL, 0x00000054UL, 0x000000bbUL, 0x00000016UL +}; + +static const ulong32 Te4_1[] = { +0x00006300UL, 0x00007c00UL, 0x00007700UL, 0x00007b00UL, 0x0000f200UL, 0x00006b00UL, 0x00006f00UL, 0x0000c500UL, +0x00003000UL, 0x00000100UL, 0x00006700UL, 0x00002b00UL, 0x0000fe00UL, 0x0000d700UL, 0x0000ab00UL, 0x00007600UL, +0x0000ca00UL, 0x00008200UL, 0x0000c900UL, 0x00007d00UL, 0x0000fa00UL, 0x00005900UL, 0x00004700UL, 0x0000f000UL, +0x0000ad00UL, 0x0000d400UL, 0x0000a200UL, 0x0000af00UL, 0x00009c00UL, 0x0000a400UL, 0x00007200UL, 0x0000c000UL, +0x0000b700UL, 0x0000fd00UL, 0x00009300UL, 0x00002600UL, 0x00003600UL, 0x00003f00UL, 0x0000f700UL, 0x0000cc00UL, +0x00003400UL, 0x0000a500UL, 0x0000e500UL, 0x0000f100UL, 0x00007100UL, 0x0000d800UL, 0x00003100UL, 0x00001500UL, +0x00000400UL, 0x0000c700UL, 0x00002300UL, 0x0000c300UL, 0x00001800UL, 0x00009600UL, 0x00000500UL, 0x00009a00UL, +0x00000700UL, 0x00001200UL, 0x00008000UL, 0x0000e200UL, 0x0000eb00UL, 0x00002700UL, 0x0000b200UL, 0x00007500UL, +0x00000900UL, 0x00008300UL, 0x00002c00UL, 0x00001a00UL, 0x00001b00UL, 0x00006e00UL, 0x00005a00UL, 0x0000a000UL, +0x00005200UL, 0x00003b00UL, 0x0000d600UL, 0x0000b300UL, 0x00002900UL, 0x0000e300UL, 0x00002f00UL, 0x00008400UL, +0x00005300UL, 0x0000d100UL, 0x00000000UL, 0x0000ed00UL, 0x00002000UL, 0x0000fc00UL, 0x0000b100UL, 0x00005b00UL, +0x00006a00UL, 0x0000cb00UL, 0x0000be00UL, 0x00003900UL, 0x00004a00UL, 0x00004c00UL, 0x00005800UL, 0x0000cf00UL, +0x0000d000UL, 0x0000ef00UL, 0x0000aa00UL, 0x0000fb00UL, 0x00004300UL, 0x00004d00UL, 0x00003300UL, 0x00008500UL, +0x00004500UL, 0x0000f900UL, 0x00000200UL, 0x00007f00UL, 0x00005000UL, 0x00003c00UL, 0x00009f00UL, 0x0000a800UL, +0x00005100UL, 0x0000a300UL, 0x00004000UL, 0x00008f00UL, 0x00009200UL, 0x00009d00UL, 0x00003800UL, 0x0000f500UL, +0x0000bc00UL, 0x0000b600UL, 0x0000da00UL, 0x00002100UL, 0x00001000UL, 0x0000ff00UL, 0x0000f300UL, 0x0000d200UL, +0x0000cd00UL, 0x00000c00UL, 0x00001300UL, 0x0000ec00UL, 0x00005f00UL, 0x00009700UL, 0x00004400UL, 0x00001700UL, +0x0000c400UL, 0x0000a700UL, 0x00007e00UL, 0x00003d00UL, 0x00006400UL, 0x00005d00UL, 0x00001900UL, 0x00007300UL, +0x00006000UL, 0x00008100UL, 0x00004f00UL, 0x0000dc00UL, 0x00002200UL, 0x00002a00UL, 0x00009000UL, 0x00008800UL, +0x00004600UL, 0x0000ee00UL, 0x0000b800UL, 0x00001400UL, 0x0000de00UL, 0x00005e00UL, 0x00000b00UL, 0x0000db00UL, +0x0000e000UL, 0x00003200UL, 0x00003a00UL, 0x00000a00UL, 0x00004900UL, 0x00000600UL, 0x00002400UL, 0x00005c00UL, +0x0000c200UL, 0x0000d300UL, 0x0000ac00UL, 0x00006200UL, 0x00009100UL, 0x00009500UL, 0x0000e400UL, 0x00007900UL, +0x0000e700UL, 0x0000c800UL, 0x00003700UL, 0x00006d00UL, 0x00008d00UL, 0x0000d500UL, 0x00004e00UL, 0x0000a900UL, +0x00006c00UL, 0x00005600UL, 0x0000f400UL, 0x0000ea00UL, 0x00006500UL, 0x00007a00UL, 0x0000ae00UL, 0x00000800UL, +0x0000ba00UL, 0x00007800UL, 0x00002500UL, 0x00002e00UL, 0x00001c00UL, 0x0000a600UL, 0x0000b400UL, 0x0000c600UL, +0x0000e800UL, 0x0000dd00UL, 0x00007400UL, 0x00001f00UL, 0x00004b00UL, 0x0000bd00UL, 0x00008b00UL, 0x00008a00UL, +0x00007000UL, 0x00003e00UL, 0x0000b500UL, 0x00006600UL, 0x00004800UL, 0x00000300UL, 0x0000f600UL, 0x00000e00UL, +0x00006100UL, 0x00003500UL, 0x00005700UL, 0x0000b900UL, 0x00008600UL, 0x0000c100UL, 0x00001d00UL, 0x00009e00UL, +0x0000e100UL, 0x0000f800UL, 0x00009800UL, 0x00001100UL, 0x00006900UL, 0x0000d900UL, 0x00008e00UL, 0x00009400UL, +0x00009b00UL, 0x00001e00UL, 0x00008700UL, 0x0000e900UL, 0x0000ce00UL, 0x00005500UL, 0x00002800UL, 0x0000df00UL, +0x00008c00UL, 0x0000a100UL, 0x00008900UL, 0x00000d00UL, 0x0000bf00UL, 0x0000e600UL, 0x00004200UL, 0x00006800UL, +0x00004100UL, 0x00009900UL, 0x00002d00UL, 0x00000f00UL, 0x0000b000UL, 0x00005400UL, 0x0000bb00UL, 0x00001600UL +}; + +static const ulong32 Te4_2[] = { +0x00630000UL, 0x007c0000UL, 0x00770000UL, 0x007b0000UL, 0x00f20000UL, 0x006b0000UL, 0x006f0000UL, 0x00c50000UL, +0x00300000UL, 0x00010000UL, 0x00670000UL, 0x002b0000UL, 0x00fe0000UL, 0x00d70000UL, 0x00ab0000UL, 0x00760000UL, +0x00ca0000UL, 0x00820000UL, 0x00c90000UL, 0x007d0000UL, 0x00fa0000UL, 0x00590000UL, 0x00470000UL, 0x00f00000UL, +0x00ad0000UL, 0x00d40000UL, 0x00a20000UL, 0x00af0000UL, 0x009c0000UL, 0x00a40000UL, 0x00720000UL, 0x00c00000UL, +0x00b70000UL, 0x00fd0000UL, 0x00930000UL, 0x00260000UL, 0x00360000UL, 0x003f0000UL, 0x00f70000UL, 0x00cc0000UL, +0x00340000UL, 0x00a50000UL, 0x00e50000UL, 0x00f10000UL, 0x00710000UL, 0x00d80000UL, 0x00310000UL, 0x00150000UL, +0x00040000UL, 0x00c70000UL, 0x00230000UL, 0x00c30000UL, 0x00180000UL, 0x00960000UL, 0x00050000UL, 0x009a0000UL, +0x00070000UL, 0x00120000UL, 0x00800000UL, 0x00e20000UL, 0x00eb0000UL, 0x00270000UL, 0x00b20000UL, 0x00750000UL, +0x00090000UL, 0x00830000UL, 0x002c0000UL, 0x001a0000UL, 0x001b0000UL, 0x006e0000UL, 0x005a0000UL, 0x00a00000UL, +0x00520000UL, 0x003b0000UL, 0x00d60000UL, 0x00b30000UL, 0x00290000UL, 0x00e30000UL, 0x002f0000UL, 0x00840000UL, +0x00530000UL, 0x00d10000UL, 0x00000000UL, 0x00ed0000UL, 0x00200000UL, 0x00fc0000UL, 0x00b10000UL, 0x005b0000UL, +0x006a0000UL, 0x00cb0000UL, 0x00be0000UL, 0x00390000UL, 0x004a0000UL, 0x004c0000UL, 0x00580000UL, 0x00cf0000UL, +0x00d00000UL, 0x00ef0000UL, 0x00aa0000UL, 0x00fb0000UL, 0x00430000UL, 0x004d0000UL, 0x00330000UL, 0x00850000UL, +0x00450000UL, 0x00f90000UL, 0x00020000UL, 0x007f0000UL, 0x00500000UL, 0x003c0000UL, 0x009f0000UL, 0x00a80000UL, +0x00510000UL, 0x00a30000UL, 0x00400000UL, 0x008f0000UL, 0x00920000UL, 0x009d0000UL, 0x00380000UL, 0x00f50000UL, +0x00bc0000UL, 0x00b60000UL, 0x00da0000UL, 0x00210000UL, 0x00100000UL, 0x00ff0000UL, 0x00f30000UL, 0x00d20000UL, +0x00cd0000UL, 0x000c0000UL, 0x00130000UL, 0x00ec0000UL, 0x005f0000UL, 0x00970000UL, 0x00440000UL, 0x00170000UL, +0x00c40000UL, 0x00a70000UL, 0x007e0000UL, 0x003d0000UL, 0x00640000UL, 0x005d0000UL, 0x00190000UL, 0x00730000UL, +0x00600000UL, 0x00810000UL, 0x004f0000UL, 0x00dc0000UL, 0x00220000UL, 0x002a0000UL, 0x00900000UL, 0x00880000UL, +0x00460000UL, 0x00ee0000UL, 0x00b80000UL, 0x00140000UL, 0x00de0000UL, 0x005e0000UL, 0x000b0000UL, 0x00db0000UL, +0x00e00000UL, 0x00320000UL, 0x003a0000UL, 0x000a0000UL, 0x00490000UL, 0x00060000UL, 0x00240000UL, 0x005c0000UL, +0x00c20000UL, 0x00d30000UL, 0x00ac0000UL, 0x00620000UL, 0x00910000UL, 0x00950000UL, 0x00e40000UL, 0x00790000UL, +0x00e70000UL, 0x00c80000UL, 0x00370000UL, 0x006d0000UL, 0x008d0000UL, 0x00d50000UL, 0x004e0000UL, 0x00a90000UL, +0x006c0000UL, 0x00560000UL, 0x00f40000UL, 0x00ea0000UL, 0x00650000UL, 0x007a0000UL, 0x00ae0000UL, 0x00080000UL, +0x00ba0000UL, 0x00780000UL, 0x00250000UL, 0x002e0000UL, 0x001c0000UL, 0x00a60000UL, 0x00b40000UL, 0x00c60000UL, +0x00e80000UL, 0x00dd0000UL, 0x00740000UL, 0x001f0000UL, 0x004b0000UL, 0x00bd0000UL, 0x008b0000UL, 0x008a0000UL, +0x00700000UL, 0x003e0000UL, 0x00b50000UL, 0x00660000UL, 0x00480000UL, 0x00030000UL, 0x00f60000UL, 0x000e0000UL, +0x00610000UL, 0x00350000UL, 0x00570000UL, 0x00b90000UL, 0x00860000UL, 0x00c10000UL, 0x001d0000UL, 0x009e0000UL, +0x00e10000UL, 0x00f80000UL, 0x00980000UL, 0x00110000UL, 0x00690000UL, 0x00d90000UL, 0x008e0000UL, 0x00940000UL, +0x009b0000UL, 0x001e0000UL, 0x00870000UL, 0x00e90000UL, 0x00ce0000UL, 0x00550000UL, 0x00280000UL, 0x00df0000UL, +0x008c0000UL, 0x00a10000UL, 0x00890000UL, 0x000d0000UL, 0x00bf0000UL, 0x00e60000UL, 0x00420000UL, 0x00680000UL, +0x00410000UL, 0x00990000UL, 0x002d0000UL, 0x000f0000UL, 0x00b00000UL, 0x00540000UL, 0x00bb0000UL, 0x00160000UL +}; + +static const ulong32 Te4_3[] = { +0x63000000UL, 0x7c000000UL, 0x77000000UL, 0x7b000000UL, 0xf2000000UL, 0x6b000000UL, 0x6f000000UL, 0xc5000000UL, +0x30000000UL, 0x01000000UL, 0x67000000UL, 0x2b000000UL, 0xfe000000UL, 0xd7000000UL, 0xab000000UL, 0x76000000UL, +0xca000000UL, 0x82000000UL, 0xc9000000UL, 0x7d000000UL, 0xfa000000UL, 0x59000000UL, 0x47000000UL, 0xf0000000UL, +0xad000000UL, 0xd4000000UL, 0xa2000000UL, 0xaf000000UL, 0x9c000000UL, 0xa4000000UL, 0x72000000UL, 0xc0000000UL, +0xb7000000UL, 0xfd000000UL, 0x93000000UL, 0x26000000UL, 0x36000000UL, 0x3f000000UL, 0xf7000000UL, 0xcc000000UL, +0x34000000UL, 0xa5000000UL, 0xe5000000UL, 0xf1000000UL, 0x71000000UL, 0xd8000000UL, 0x31000000UL, 0x15000000UL, +0x04000000UL, 0xc7000000UL, 0x23000000UL, 0xc3000000UL, 0x18000000UL, 0x96000000UL, 0x05000000UL, 0x9a000000UL, +0x07000000UL, 0x12000000UL, 0x80000000UL, 0xe2000000UL, 0xeb000000UL, 0x27000000UL, 0xb2000000UL, 0x75000000UL, +0x09000000UL, 0x83000000UL, 0x2c000000UL, 0x1a000000UL, 0x1b000000UL, 0x6e000000UL, 0x5a000000UL, 0xa0000000UL, +0x52000000UL, 0x3b000000UL, 0xd6000000UL, 0xb3000000UL, 0x29000000UL, 0xe3000000UL, 0x2f000000UL, 0x84000000UL, +0x53000000UL, 0xd1000000UL, 0x00000000UL, 0xed000000UL, 0x20000000UL, 0xfc000000UL, 0xb1000000UL, 0x5b000000UL, +0x6a000000UL, 0xcb000000UL, 0xbe000000UL, 0x39000000UL, 0x4a000000UL, 0x4c000000UL, 0x58000000UL, 0xcf000000UL, +0xd0000000UL, 0xef000000UL, 0xaa000000UL, 0xfb000000UL, 0x43000000UL, 0x4d000000UL, 0x33000000UL, 0x85000000UL, +0x45000000UL, 0xf9000000UL, 0x02000000UL, 0x7f000000UL, 0x50000000UL, 0x3c000000UL, 0x9f000000UL, 0xa8000000UL, +0x51000000UL, 0xa3000000UL, 0x40000000UL, 0x8f000000UL, 0x92000000UL, 0x9d000000UL, 0x38000000UL, 0xf5000000UL, +0xbc000000UL, 0xb6000000UL, 0xda000000UL, 0x21000000UL, 0x10000000UL, 0xff000000UL, 0xf3000000UL, 0xd2000000UL, +0xcd000000UL, 0x0c000000UL, 0x13000000UL, 0xec000000UL, 0x5f000000UL, 0x97000000UL, 0x44000000UL, 0x17000000UL, +0xc4000000UL, 0xa7000000UL, 0x7e000000UL, 0x3d000000UL, 0x64000000UL, 0x5d000000UL, 0x19000000UL, 0x73000000UL, +0x60000000UL, 0x81000000UL, 0x4f000000UL, 0xdc000000UL, 0x22000000UL, 0x2a000000UL, 0x90000000UL, 0x88000000UL, +0x46000000UL, 0xee000000UL, 0xb8000000UL, 0x14000000UL, 0xde000000UL, 0x5e000000UL, 0x0b000000UL, 0xdb000000UL, +0xe0000000UL, 0x32000000UL, 0x3a000000UL, 0x0a000000UL, 0x49000000UL, 0x06000000UL, 0x24000000UL, 0x5c000000UL, +0xc2000000UL, 0xd3000000UL, 0xac000000UL, 0x62000000UL, 0x91000000UL, 0x95000000UL, 0xe4000000UL, 0x79000000UL, +0xe7000000UL, 0xc8000000UL, 0x37000000UL, 0x6d000000UL, 0x8d000000UL, 0xd5000000UL, 0x4e000000UL, 0xa9000000UL, +0x6c000000UL, 0x56000000UL, 0xf4000000UL, 0xea000000UL, 0x65000000UL, 0x7a000000UL, 0xae000000UL, 0x08000000UL, +0xba000000UL, 0x78000000UL, 0x25000000UL, 0x2e000000UL, 0x1c000000UL, 0xa6000000UL, 0xb4000000UL, 0xc6000000UL, +0xe8000000UL, 0xdd000000UL, 0x74000000UL, 0x1f000000UL, 0x4b000000UL, 0xbd000000UL, 0x8b000000UL, 0x8a000000UL, +0x70000000UL, 0x3e000000UL, 0xb5000000UL, 0x66000000UL, 0x48000000UL, 0x03000000UL, 0xf6000000UL, 0x0e000000UL, +0x61000000UL, 0x35000000UL, 0x57000000UL, 0xb9000000UL, 0x86000000UL, 0xc1000000UL, 0x1d000000UL, 0x9e000000UL, +0xe1000000UL, 0xf8000000UL, 0x98000000UL, 0x11000000UL, 0x69000000UL, 0xd9000000UL, 0x8e000000UL, 0x94000000UL, +0x9b000000UL, 0x1e000000UL, 0x87000000UL, 0xe9000000UL, 0xce000000UL, 0x55000000UL, 0x28000000UL, 0xdf000000UL, +0x8c000000UL, 0xa1000000UL, 0x89000000UL, 0x0d000000UL, 0xbf000000UL, 0xe6000000UL, 0x42000000UL, 0x68000000UL, +0x41000000UL, 0x99000000UL, 0x2d000000UL, 0x0f000000UL, 0xb0000000UL, 0x54000000UL, 0xbb000000UL, 0x16000000UL +}; +#endif /* pelimac */ + +#ifndef ENCRYPT_ONLY + +static const ulong32 TD1[256] = { + 0x5051f4a7UL, 0x537e4165UL, 0xc31a17a4UL, 0x963a275eUL, + 0xcb3bab6bUL, 0xf11f9d45UL, 0xabacfa58UL, 0x934be303UL, + 0x552030faUL, 0xf6ad766dUL, 0x9188cc76UL, 0x25f5024cUL, + 0xfc4fe5d7UL, 0xd7c52acbUL, 0x80263544UL, 0x8fb562a3UL, + 0x49deb15aUL, 0x6725ba1bUL, 0x9845ea0eUL, 0xe15dfec0UL, + 0x02c32f75UL, 0x12814cf0UL, 0xa38d4697UL, 0xc66bd3f9UL, + 0xe7038f5fUL, 0x9515929cUL, 0xebbf6d7aUL, 0xda955259UL, + 0x2dd4be83UL, 0xd3587421UL, 0x2949e069UL, 0x448ec9c8UL, + 0x6a75c289UL, 0x78f48e79UL, 0x6b99583eUL, 0xdd27b971UL, + 0xb6bee14fUL, 0x17f088adUL, 0x66c920acUL, 0xb47dce3aUL, + 0x1863df4aUL, 0x82e51a31UL, 0x60975133UL, 0x4562537fUL, + 0xe0b16477UL, 0x84bb6baeUL, 0x1cfe81a0UL, 0x94f9082bUL, + 0x58704868UL, 0x198f45fdUL, 0x8794de6cUL, 0xb7527bf8UL, + 0x23ab73d3UL, 0xe2724b02UL, 0x57e31f8fUL, 0x2a6655abUL, + 0x07b2eb28UL, 0x032fb5c2UL, 0x9a86c57bUL, 0xa5d33708UL, + 0xf2302887UL, 0xb223bfa5UL, 0xba02036aUL, 0x5ced1682UL, + 0x2b8acf1cUL, 0x92a779b4UL, 0xf0f307f2UL, 0xa14e69e2UL, + 0xcd65daf4UL, 0xd50605beUL, 0x1fd13462UL, 0x8ac4a6feUL, + 0x9d342e53UL, 0xa0a2f355UL, 0x32058ae1UL, 0x75a4f6ebUL, + 0x390b83ecUL, 0xaa4060efUL, 0x065e719fUL, 0x51bd6e10UL, + 0xf93e218aUL, 0x3d96dd06UL, 0xaedd3e05UL, 0x464de6bdUL, + 0xb591548dUL, 0x0571c45dUL, 0x6f0406d4UL, 0xff605015UL, + 0x241998fbUL, 0x97d6bde9UL, 0xcc894043UL, 0x7767d99eUL, + 0xbdb0e842UL, 0x8807898bUL, 0x38e7195bUL, 0xdb79c8eeUL, + 0x47a17c0aUL, 0xe97c420fUL, 0xc9f8841eUL, 0x00000000UL, + 0x83098086UL, 0x48322bedUL, 0xac1e1170UL, 0x4e6c5a72UL, + 0xfbfd0effUL, 0x560f8538UL, 0x1e3daed5UL, 0x27362d39UL, + 0x640a0fd9UL, 0x21685ca6UL, 0xd19b5b54UL, 0x3a24362eUL, + 0xb10c0a67UL, 0x0f9357e7UL, 0xd2b4ee96UL, 0x9e1b9b91UL, + 0x4f80c0c5UL, 0xa261dc20UL, 0x695a774bUL, 0x161c121aUL, + 0x0ae293baUL, 0xe5c0a02aUL, 0x433c22e0UL, 0x1d121b17UL, + 0x0b0e090dUL, 0xadf28bc7UL, 0xb92db6a8UL, 0xc8141ea9UL, + 0x8557f119UL, 0x4caf7507UL, 0xbbee99ddUL, 0xfda37f60UL, + 0x9ff70126UL, 0xbc5c72f5UL, 0xc544663bUL, 0x345bfb7eUL, + 0x768b4329UL, 0xdccb23c6UL, 0x68b6edfcUL, 0x63b8e4f1UL, + 0xcad731dcUL, 0x10426385UL, 0x40139722UL, 0x2084c611UL, + 0x7d854a24UL, 0xf8d2bb3dUL, 0x11aef932UL, 0x6dc729a1UL, + 0x4b1d9e2fUL, 0xf3dcb230UL, 0xec0d8652UL, 0xd077c1e3UL, + 0x6c2bb316UL, 0x99a970b9UL, 0xfa119448UL, 0x2247e964UL, + 0xc4a8fc8cUL, 0x1aa0f03fUL, 0xd8567d2cUL, 0xef223390UL, + 0xc787494eUL, 0xc1d938d1UL, 0xfe8ccaa2UL, 0x3698d40bUL, + 0xcfa6f581UL, 0x28a57adeUL, 0x26dab78eUL, 0xa43fadbfUL, + 0xe42c3a9dUL, 0x0d507892UL, 0x9b6a5fccUL, 0x62547e46UL, + 0xc2f68d13UL, 0xe890d8b8UL, 0x5e2e39f7UL, 0xf582c3afUL, + 0xbe9f5d80UL, 0x7c69d093UL, 0xa96fd52dUL, 0xb3cf2512UL, + 0x3bc8ac99UL, 0xa710187dUL, 0x6ee89c63UL, 0x7bdb3bbbUL, + 0x09cd2678UL, 0xf46e5918UL, 0x01ec9ab7UL, 0xa8834f9aUL, + 0x65e6956eUL, 0x7eaaffe6UL, 0x0821bccfUL, 0xe6ef15e8UL, + 0xd9bae79bUL, 0xce4a6f36UL, 0xd4ea9f09UL, 0xd629b07cUL, + 0xaf31a4b2UL, 0x312a3f23UL, 0x30c6a594UL, 0xc035a266UL, + 0x37744ebcUL, 0xa6fc82caUL, 0xb0e090d0UL, 0x1533a7d8UL, + 0x4af10498UL, 0xf741ecdaUL, 0x0e7fcd50UL, 0x2f1791f6UL, + 0x8d764dd6UL, 0x4d43efb0UL, 0x54ccaa4dUL, 0xdfe49604UL, + 0xe39ed1b5UL, 0x1b4c6a88UL, 0xb8c12c1fUL, 0x7f466551UL, + 0x049d5eeaUL, 0x5d018c35UL, 0x73fa8774UL, 0x2efb0b41UL, + 0x5ab3671dUL, 0x5292dbd2UL, 0x33e91056UL, 0x136dd647UL, + 0x8c9ad761UL, 0x7a37a10cUL, 0x8e59f814UL, 0x89eb133cUL, + 0xeecea927UL, 0x35b761c9UL, 0xede11ce5UL, 0x3c7a47b1UL, + 0x599cd2dfUL, 0x3f55f273UL, 0x791814ceUL, 0xbf73c737UL, + 0xea53f7cdUL, 0x5b5ffdaaUL, 0x14df3d6fUL, 0x867844dbUL, + 0x81caaff3UL, 0x3eb968c4UL, 0x2c382434UL, 0x5fc2a340UL, + 0x72161dc3UL, 0x0cbce225UL, 0x8b283c49UL, 0x41ff0d95UL, + 0x7139a801UL, 0xde080cb3UL, 0x9cd8b4e4UL, 0x906456c1UL, + 0x617bcb84UL, 0x70d532b6UL, 0x74486c5cUL, 0x42d0b857UL, +}; +static const ulong32 TD2[256] = { + 0xa75051f4UL, 0x65537e41UL, 0xa4c31a17UL, 0x5e963a27UL, + 0x6bcb3babUL, 0x45f11f9dUL, 0x58abacfaUL, 0x03934be3UL, + 0xfa552030UL, 0x6df6ad76UL, 0x769188ccUL, 0x4c25f502UL, + 0xd7fc4fe5UL, 0xcbd7c52aUL, 0x44802635UL, 0xa38fb562UL, + 0x5a49deb1UL, 0x1b6725baUL, 0x0e9845eaUL, 0xc0e15dfeUL, + 0x7502c32fUL, 0xf012814cUL, 0x97a38d46UL, 0xf9c66bd3UL, + 0x5fe7038fUL, 0x9c951592UL, 0x7aebbf6dUL, 0x59da9552UL, + 0x832dd4beUL, 0x21d35874UL, 0x692949e0UL, 0xc8448ec9UL, + 0x896a75c2UL, 0x7978f48eUL, 0x3e6b9958UL, 0x71dd27b9UL, + 0x4fb6bee1UL, 0xad17f088UL, 0xac66c920UL, 0x3ab47dceUL, + 0x4a1863dfUL, 0x3182e51aUL, 0x33609751UL, 0x7f456253UL, + 0x77e0b164UL, 0xae84bb6bUL, 0xa01cfe81UL, 0x2b94f908UL, + 0x68587048UL, 0xfd198f45UL, 0x6c8794deUL, 0xf8b7527bUL, + 0xd323ab73UL, 0x02e2724bUL, 0x8f57e31fUL, 0xab2a6655UL, + 0x2807b2ebUL, 0xc2032fb5UL, 0x7b9a86c5UL, 0x08a5d337UL, + 0x87f23028UL, 0xa5b223bfUL, 0x6aba0203UL, 0x825ced16UL, + 0x1c2b8acfUL, 0xb492a779UL, 0xf2f0f307UL, 0xe2a14e69UL, + 0xf4cd65daUL, 0xbed50605UL, 0x621fd134UL, 0xfe8ac4a6UL, + 0x539d342eUL, 0x55a0a2f3UL, 0xe132058aUL, 0xeb75a4f6UL, + 0xec390b83UL, 0xefaa4060UL, 0x9f065e71UL, 0x1051bd6eUL, + 0x8af93e21UL, 0x063d96ddUL, 0x05aedd3eUL, 0xbd464de6UL, + 0x8db59154UL, 0x5d0571c4UL, 0xd46f0406UL, 0x15ff6050UL, + 0xfb241998UL, 0xe997d6bdUL, 0x43cc8940UL, 0x9e7767d9UL, + 0x42bdb0e8UL, 0x8b880789UL, 0x5b38e719UL, 0xeedb79c8UL, + 0x0a47a17cUL, 0x0fe97c42UL, 0x1ec9f884UL, 0x00000000UL, + 0x86830980UL, 0xed48322bUL, 0x70ac1e11UL, 0x724e6c5aUL, + 0xfffbfd0eUL, 0x38560f85UL, 0xd51e3daeUL, 0x3927362dUL, + 0xd9640a0fUL, 0xa621685cUL, 0x54d19b5bUL, 0x2e3a2436UL, + 0x67b10c0aUL, 0xe70f9357UL, 0x96d2b4eeUL, 0x919e1b9bUL, + 0xc54f80c0UL, 0x20a261dcUL, 0x4b695a77UL, 0x1a161c12UL, + 0xba0ae293UL, 0x2ae5c0a0UL, 0xe0433c22UL, 0x171d121bUL, + 0x0d0b0e09UL, 0xc7adf28bUL, 0xa8b92db6UL, 0xa9c8141eUL, + 0x198557f1UL, 0x074caf75UL, 0xddbbee99UL, 0x60fda37fUL, + 0x269ff701UL, 0xf5bc5c72UL, 0x3bc54466UL, 0x7e345bfbUL, + 0x29768b43UL, 0xc6dccb23UL, 0xfc68b6edUL, 0xf163b8e4UL, + 0xdccad731UL, 0x85104263UL, 0x22401397UL, 0x112084c6UL, + 0x247d854aUL, 0x3df8d2bbUL, 0x3211aef9UL, 0xa16dc729UL, + 0x2f4b1d9eUL, 0x30f3dcb2UL, 0x52ec0d86UL, 0xe3d077c1UL, + 0x166c2bb3UL, 0xb999a970UL, 0x48fa1194UL, 0x642247e9UL, + 0x8cc4a8fcUL, 0x3f1aa0f0UL, 0x2cd8567dUL, 0x90ef2233UL, + 0x4ec78749UL, 0xd1c1d938UL, 0xa2fe8ccaUL, 0x0b3698d4UL, + 0x81cfa6f5UL, 0xde28a57aUL, 0x8e26dab7UL, 0xbfa43fadUL, + 0x9de42c3aUL, 0x920d5078UL, 0xcc9b6a5fUL, 0x4662547eUL, + 0x13c2f68dUL, 0xb8e890d8UL, 0xf75e2e39UL, 0xaff582c3UL, + 0x80be9f5dUL, 0x937c69d0UL, 0x2da96fd5UL, 0x12b3cf25UL, + 0x993bc8acUL, 0x7da71018UL, 0x636ee89cUL, 0xbb7bdb3bUL, + 0x7809cd26UL, 0x18f46e59UL, 0xb701ec9aUL, 0x9aa8834fUL, + 0x6e65e695UL, 0xe67eaaffUL, 0xcf0821bcUL, 0xe8e6ef15UL, + 0x9bd9bae7UL, 0x36ce4a6fUL, 0x09d4ea9fUL, 0x7cd629b0UL, + 0xb2af31a4UL, 0x23312a3fUL, 0x9430c6a5UL, 0x66c035a2UL, + 0xbc37744eUL, 0xcaa6fc82UL, 0xd0b0e090UL, 0xd81533a7UL, + 0x984af104UL, 0xdaf741ecUL, 0x500e7fcdUL, 0xf62f1791UL, + 0xd68d764dUL, 0xb04d43efUL, 0x4d54ccaaUL, 0x04dfe496UL, + 0xb5e39ed1UL, 0x881b4c6aUL, 0x1fb8c12cUL, 0x517f4665UL, + 0xea049d5eUL, 0x355d018cUL, 0x7473fa87UL, 0x412efb0bUL, + 0x1d5ab367UL, 0xd25292dbUL, 0x5633e910UL, 0x47136dd6UL, + 0x618c9ad7UL, 0x0c7a37a1UL, 0x148e59f8UL, 0x3c89eb13UL, + 0x27eecea9UL, 0xc935b761UL, 0xe5ede11cUL, 0xb13c7a47UL, + 0xdf599cd2UL, 0x733f55f2UL, 0xce791814UL, 0x37bf73c7UL, + 0xcdea53f7UL, 0xaa5b5ffdUL, 0x6f14df3dUL, 0xdb867844UL, + 0xf381caafUL, 0xc43eb968UL, 0x342c3824UL, 0x405fc2a3UL, + 0xc372161dUL, 0x250cbce2UL, 0x498b283cUL, 0x9541ff0dUL, + 0x017139a8UL, 0xb3de080cUL, 0xe49cd8b4UL, 0xc1906456UL, + 0x84617bcbUL, 0xb670d532UL, 0x5c74486cUL, 0x5742d0b8UL, +}; +static const ulong32 TD3[256] = { + 0xf4a75051UL, 0x4165537eUL, 0x17a4c31aUL, 0x275e963aUL, + 0xab6bcb3bUL, 0x9d45f11fUL, 0xfa58abacUL, 0xe303934bUL, + 0x30fa5520UL, 0x766df6adUL, 0xcc769188UL, 0x024c25f5UL, + 0xe5d7fc4fUL, 0x2acbd7c5UL, 0x35448026UL, 0x62a38fb5UL, + 0xb15a49deUL, 0xba1b6725UL, 0xea0e9845UL, 0xfec0e15dUL, + 0x2f7502c3UL, 0x4cf01281UL, 0x4697a38dUL, 0xd3f9c66bUL, + 0x8f5fe703UL, 0x929c9515UL, 0x6d7aebbfUL, 0x5259da95UL, + 0xbe832dd4UL, 0x7421d358UL, 0xe0692949UL, 0xc9c8448eUL, + 0xc2896a75UL, 0x8e7978f4UL, 0x583e6b99UL, 0xb971dd27UL, + 0xe14fb6beUL, 0x88ad17f0UL, 0x20ac66c9UL, 0xce3ab47dUL, + 0xdf4a1863UL, 0x1a3182e5UL, 0x51336097UL, 0x537f4562UL, + 0x6477e0b1UL, 0x6bae84bbUL, 0x81a01cfeUL, 0x082b94f9UL, + 0x48685870UL, 0x45fd198fUL, 0xde6c8794UL, 0x7bf8b752UL, + 0x73d323abUL, 0x4b02e272UL, 0x1f8f57e3UL, 0x55ab2a66UL, + 0xeb2807b2UL, 0xb5c2032fUL, 0xc57b9a86UL, 0x3708a5d3UL, + 0x2887f230UL, 0xbfa5b223UL, 0x036aba02UL, 0x16825cedUL, + 0xcf1c2b8aUL, 0x79b492a7UL, 0x07f2f0f3UL, 0x69e2a14eUL, + 0xdaf4cd65UL, 0x05bed506UL, 0x34621fd1UL, 0xa6fe8ac4UL, + 0x2e539d34UL, 0xf355a0a2UL, 0x8ae13205UL, 0xf6eb75a4UL, + 0x83ec390bUL, 0x60efaa40UL, 0x719f065eUL, 0x6e1051bdUL, + 0x218af93eUL, 0xdd063d96UL, 0x3e05aeddUL, 0xe6bd464dUL, + 0x548db591UL, 0xc45d0571UL, 0x06d46f04UL, 0x5015ff60UL, + 0x98fb2419UL, 0xbde997d6UL, 0x4043cc89UL, 0xd99e7767UL, + 0xe842bdb0UL, 0x898b8807UL, 0x195b38e7UL, 0xc8eedb79UL, + 0x7c0a47a1UL, 0x420fe97cUL, 0x841ec9f8UL, 0x00000000UL, + 0x80868309UL, 0x2bed4832UL, 0x1170ac1eUL, 0x5a724e6cUL, + 0x0efffbfdUL, 0x8538560fUL, 0xaed51e3dUL, 0x2d392736UL, + 0x0fd9640aUL, 0x5ca62168UL, 0x5b54d19bUL, 0x362e3a24UL, + 0x0a67b10cUL, 0x57e70f93UL, 0xee96d2b4UL, 0x9b919e1bUL, + 0xc0c54f80UL, 0xdc20a261UL, 0x774b695aUL, 0x121a161cUL, + 0x93ba0ae2UL, 0xa02ae5c0UL, 0x22e0433cUL, 0x1b171d12UL, + 0x090d0b0eUL, 0x8bc7adf2UL, 0xb6a8b92dUL, 0x1ea9c814UL, + 0xf1198557UL, 0x75074cafUL, 0x99ddbbeeUL, 0x7f60fda3UL, + 0x01269ff7UL, 0x72f5bc5cUL, 0x663bc544UL, 0xfb7e345bUL, + 0x4329768bUL, 0x23c6dccbUL, 0xedfc68b6UL, 0xe4f163b8UL, + 0x31dccad7UL, 0x63851042UL, 0x97224013UL, 0xc6112084UL, + 0x4a247d85UL, 0xbb3df8d2UL, 0xf93211aeUL, 0x29a16dc7UL, + 0x9e2f4b1dUL, 0xb230f3dcUL, 0x8652ec0dUL, 0xc1e3d077UL, + 0xb3166c2bUL, 0x70b999a9UL, 0x9448fa11UL, 0xe9642247UL, + 0xfc8cc4a8UL, 0xf03f1aa0UL, 0x7d2cd856UL, 0x3390ef22UL, + 0x494ec787UL, 0x38d1c1d9UL, 0xcaa2fe8cUL, 0xd40b3698UL, + 0xf581cfa6UL, 0x7ade28a5UL, 0xb78e26daUL, 0xadbfa43fUL, + 0x3a9de42cUL, 0x78920d50UL, 0x5fcc9b6aUL, 0x7e466254UL, + 0x8d13c2f6UL, 0xd8b8e890UL, 0x39f75e2eUL, 0xc3aff582UL, + 0x5d80be9fUL, 0xd0937c69UL, 0xd52da96fUL, 0x2512b3cfUL, + 0xac993bc8UL, 0x187da710UL, 0x9c636ee8UL, 0x3bbb7bdbUL, + 0x267809cdUL, 0x5918f46eUL, 0x9ab701ecUL, 0x4f9aa883UL, + 0x956e65e6UL, 0xffe67eaaUL, 0xbccf0821UL, 0x15e8e6efUL, + 0xe79bd9baUL, 0x6f36ce4aUL, 0x9f09d4eaUL, 0xb07cd629UL, + 0xa4b2af31UL, 0x3f23312aUL, 0xa59430c6UL, 0xa266c035UL, + 0x4ebc3774UL, 0x82caa6fcUL, 0x90d0b0e0UL, 0xa7d81533UL, + 0x04984af1UL, 0xecdaf741UL, 0xcd500e7fUL, 0x91f62f17UL, + 0x4dd68d76UL, 0xefb04d43UL, 0xaa4d54ccUL, 0x9604dfe4UL, + 0xd1b5e39eUL, 0x6a881b4cUL, 0x2c1fb8c1UL, 0x65517f46UL, + 0x5eea049dUL, 0x8c355d01UL, 0x877473faUL, 0x0b412efbUL, + 0x671d5ab3UL, 0xdbd25292UL, 0x105633e9UL, 0xd647136dUL, + 0xd7618c9aUL, 0xa10c7a37UL, 0xf8148e59UL, 0x133c89ebUL, + 0xa927eeceUL, 0x61c935b7UL, 0x1ce5ede1UL, 0x47b13c7aUL, + 0xd2df599cUL, 0xf2733f55UL, 0x14ce7918UL, 0xc737bf73UL, + 0xf7cdea53UL, 0xfdaa5b5fUL, 0x3d6f14dfUL, 0x44db8678UL, + 0xaff381caUL, 0x68c43eb9UL, 0x24342c38UL, 0xa3405fc2UL, + 0x1dc37216UL, 0xe2250cbcUL, 0x3c498b28UL, 0x0d9541ffUL, + 0xa8017139UL, 0x0cb3de08UL, 0xb4e49cd8UL, 0x56c19064UL, + 0xcb84617bUL, 0x32b670d5UL, 0x6c5c7448UL, 0xb85742d0UL, +}; + +static const ulong32 Tks0[] = { +0x00000000UL, 0x0e090d0bUL, 0x1c121a16UL, 0x121b171dUL, 0x3824342cUL, 0x362d3927UL, 0x24362e3aUL, 0x2a3f2331UL, +0x70486858UL, 0x7e416553UL, 0x6c5a724eUL, 0x62537f45UL, 0x486c5c74UL, 0x4665517fUL, 0x547e4662UL, 0x5a774b69UL, +0xe090d0b0UL, 0xee99ddbbUL, 0xfc82caa6UL, 0xf28bc7adUL, 0xd8b4e49cUL, 0xd6bde997UL, 0xc4a6fe8aUL, 0xcaaff381UL, +0x90d8b8e8UL, 0x9ed1b5e3UL, 0x8ccaa2feUL, 0x82c3aff5UL, 0xa8fc8cc4UL, 0xa6f581cfUL, 0xb4ee96d2UL, 0xbae79bd9UL, +0xdb3bbb7bUL, 0xd532b670UL, 0xc729a16dUL, 0xc920ac66UL, 0xe31f8f57UL, 0xed16825cUL, 0xff0d9541UL, 0xf104984aUL, +0xab73d323UL, 0xa57ade28UL, 0xb761c935UL, 0xb968c43eUL, 0x9357e70fUL, 0x9d5eea04UL, 0x8f45fd19UL, 0x814cf012UL, +0x3bab6bcbUL, 0x35a266c0UL, 0x27b971ddUL, 0x29b07cd6UL, 0x038f5fe7UL, 0x0d8652ecUL, 0x1f9d45f1UL, 0x119448faUL, +0x4be30393UL, 0x45ea0e98UL, 0x57f11985UL, 0x59f8148eUL, 0x73c737bfUL, 0x7dce3ab4UL, 0x6fd52da9UL, 0x61dc20a2UL, +0xad766df6UL, 0xa37f60fdUL, 0xb16477e0UL, 0xbf6d7aebUL, 0x955259daUL, 0x9b5b54d1UL, 0x894043ccUL, 0x87494ec7UL, +0xdd3e05aeUL, 0xd33708a5UL, 0xc12c1fb8UL, 0xcf2512b3UL, 0xe51a3182UL, 0xeb133c89UL, 0xf9082b94UL, 0xf701269fUL, +0x4de6bd46UL, 0x43efb04dUL, 0x51f4a750UL, 0x5ffdaa5bUL, 0x75c2896aUL, 0x7bcb8461UL, 0x69d0937cUL, 0x67d99e77UL, +0x3daed51eUL, 0x33a7d815UL, 0x21bccf08UL, 0x2fb5c203UL, 0x058ae132UL, 0x0b83ec39UL, 0x1998fb24UL, 0x1791f62fUL, +0x764dd68dUL, 0x7844db86UL, 0x6a5fcc9bUL, 0x6456c190UL, 0x4e69e2a1UL, 0x4060efaaUL, 0x527bf8b7UL, 0x5c72f5bcUL, +0x0605bed5UL, 0x080cb3deUL, 0x1a17a4c3UL, 0x141ea9c8UL, 0x3e218af9UL, 0x302887f2UL, 0x223390efUL, 0x2c3a9de4UL, +0x96dd063dUL, 0x98d40b36UL, 0x8acf1c2bUL, 0x84c61120UL, 0xaef93211UL, 0xa0f03f1aUL, 0xb2eb2807UL, 0xbce2250cUL, +0xe6956e65UL, 0xe89c636eUL, 0xfa877473UL, 0xf48e7978UL, 0xdeb15a49UL, 0xd0b85742UL, 0xc2a3405fUL, 0xccaa4d54UL, +0x41ecdaf7UL, 0x4fe5d7fcUL, 0x5dfec0e1UL, 0x53f7cdeaUL, 0x79c8eedbUL, 0x77c1e3d0UL, 0x65daf4cdUL, 0x6bd3f9c6UL, +0x31a4b2afUL, 0x3fadbfa4UL, 0x2db6a8b9UL, 0x23bfa5b2UL, 0x09808683UL, 0x07898b88UL, 0x15929c95UL, 0x1b9b919eUL, +0xa17c0a47UL, 0xaf75074cUL, 0xbd6e1051UL, 0xb3671d5aUL, 0x99583e6bUL, 0x97513360UL, 0x854a247dUL, 0x8b432976UL, +0xd134621fUL, 0xdf3d6f14UL, 0xcd267809UL, 0xc32f7502UL, 0xe9105633UL, 0xe7195b38UL, 0xf5024c25UL, 0xfb0b412eUL, +0x9ad7618cUL, 0x94de6c87UL, 0x86c57b9aUL, 0x88cc7691UL, 0xa2f355a0UL, 0xacfa58abUL, 0xbee14fb6UL, 0xb0e842bdUL, +0xea9f09d4UL, 0xe49604dfUL, 0xf68d13c2UL, 0xf8841ec9UL, 0xd2bb3df8UL, 0xdcb230f3UL, 0xcea927eeUL, 0xc0a02ae5UL, +0x7a47b13cUL, 0x744ebc37UL, 0x6655ab2aUL, 0x685ca621UL, 0x42638510UL, 0x4c6a881bUL, 0x5e719f06UL, 0x5078920dUL, +0x0a0fd964UL, 0x0406d46fUL, 0x161dc372UL, 0x1814ce79UL, 0x322bed48UL, 0x3c22e043UL, 0x2e39f75eUL, 0x2030fa55UL, +0xec9ab701UL, 0xe293ba0aUL, 0xf088ad17UL, 0xfe81a01cUL, 0xd4be832dUL, 0xdab78e26UL, 0xc8ac993bUL, 0xc6a59430UL, +0x9cd2df59UL, 0x92dbd252UL, 0x80c0c54fUL, 0x8ec9c844UL, 0xa4f6eb75UL, 0xaaffe67eUL, 0xb8e4f163UL, 0xb6edfc68UL, +0x0c0a67b1UL, 0x02036abaUL, 0x10187da7UL, 0x1e1170acUL, 0x342e539dUL, 0x3a275e96UL, 0x283c498bUL, 0x26354480UL, +0x7c420fe9UL, 0x724b02e2UL, 0x605015ffUL, 0x6e5918f4UL, 0x44663bc5UL, 0x4a6f36ceUL, 0x587421d3UL, 0x567d2cd8UL, +0x37a10c7aUL, 0x39a80171UL, 0x2bb3166cUL, 0x25ba1b67UL, 0x0f853856UL, 0x018c355dUL, 0x13972240UL, 0x1d9e2f4bUL, +0x47e96422UL, 0x49e06929UL, 0x5bfb7e34UL, 0x55f2733fUL, 0x7fcd500eUL, 0x71c45d05UL, 0x63df4a18UL, 0x6dd64713UL, +0xd731dccaUL, 0xd938d1c1UL, 0xcb23c6dcUL, 0xc52acbd7UL, 0xef15e8e6UL, 0xe11ce5edUL, 0xf307f2f0UL, 0xfd0efffbUL, +0xa779b492UL, 0xa970b999UL, 0xbb6bae84UL, 0xb562a38fUL, 0x9f5d80beUL, 0x91548db5UL, 0x834f9aa8UL, 0x8d4697a3UL +}; + +static const ulong32 Tks1[] = { +0x00000000UL, 0x0b0e090dUL, 0x161c121aUL, 0x1d121b17UL, 0x2c382434UL, 0x27362d39UL, 0x3a24362eUL, 0x312a3f23UL, +0x58704868UL, 0x537e4165UL, 0x4e6c5a72UL, 0x4562537fUL, 0x74486c5cUL, 0x7f466551UL, 0x62547e46UL, 0x695a774bUL, +0xb0e090d0UL, 0xbbee99ddUL, 0xa6fc82caUL, 0xadf28bc7UL, 0x9cd8b4e4UL, 0x97d6bde9UL, 0x8ac4a6feUL, 0x81caaff3UL, +0xe890d8b8UL, 0xe39ed1b5UL, 0xfe8ccaa2UL, 0xf582c3afUL, 0xc4a8fc8cUL, 0xcfa6f581UL, 0xd2b4ee96UL, 0xd9bae79bUL, +0x7bdb3bbbUL, 0x70d532b6UL, 0x6dc729a1UL, 0x66c920acUL, 0x57e31f8fUL, 0x5ced1682UL, 0x41ff0d95UL, 0x4af10498UL, +0x23ab73d3UL, 0x28a57adeUL, 0x35b761c9UL, 0x3eb968c4UL, 0x0f9357e7UL, 0x049d5eeaUL, 0x198f45fdUL, 0x12814cf0UL, +0xcb3bab6bUL, 0xc035a266UL, 0xdd27b971UL, 0xd629b07cUL, 0xe7038f5fUL, 0xec0d8652UL, 0xf11f9d45UL, 0xfa119448UL, +0x934be303UL, 0x9845ea0eUL, 0x8557f119UL, 0x8e59f814UL, 0xbf73c737UL, 0xb47dce3aUL, 0xa96fd52dUL, 0xa261dc20UL, +0xf6ad766dUL, 0xfda37f60UL, 0xe0b16477UL, 0xebbf6d7aUL, 0xda955259UL, 0xd19b5b54UL, 0xcc894043UL, 0xc787494eUL, +0xaedd3e05UL, 0xa5d33708UL, 0xb8c12c1fUL, 0xb3cf2512UL, 0x82e51a31UL, 0x89eb133cUL, 0x94f9082bUL, 0x9ff70126UL, +0x464de6bdUL, 0x4d43efb0UL, 0x5051f4a7UL, 0x5b5ffdaaUL, 0x6a75c289UL, 0x617bcb84UL, 0x7c69d093UL, 0x7767d99eUL, +0x1e3daed5UL, 0x1533a7d8UL, 0x0821bccfUL, 0x032fb5c2UL, 0x32058ae1UL, 0x390b83ecUL, 0x241998fbUL, 0x2f1791f6UL, +0x8d764dd6UL, 0x867844dbUL, 0x9b6a5fccUL, 0x906456c1UL, 0xa14e69e2UL, 0xaa4060efUL, 0xb7527bf8UL, 0xbc5c72f5UL, +0xd50605beUL, 0xde080cb3UL, 0xc31a17a4UL, 0xc8141ea9UL, 0xf93e218aUL, 0xf2302887UL, 0xef223390UL, 0xe42c3a9dUL, +0x3d96dd06UL, 0x3698d40bUL, 0x2b8acf1cUL, 0x2084c611UL, 0x11aef932UL, 0x1aa0f03fUL, 0x07b2eb28UL, 0x0cbce225UL, +0x65e6956eUL, 0x6ee89c63UL, 0x73fa8774UL, 0x78f48e79UL, 0x49deb15aUL, 0x42d0b857UL, 0x5fc2a340UL, 0x54ccaa4dUL, +0xf741ecdaUL, 0xfc4fe5d7UL, 0xe15dfec0UL, 0xea53f7cdUL, 0xdb79c8eeUL, 0xd077c1e3UL, 0xcd65daf4UL, 0xc66bd3f9UL, +0xaf31a4b2UL, 0xa43fadbfUL, 0xb92db6a8UL, 0xb223bfa5UL, 0x83098086UL, 0x8807898bUL, 0x9515929cUL, 0x9e1b9b91UL, +0x47a17c0aUL, 0x4caf7507UL, 0x51bd6e10UL, 0x5ab3671dUL, 0x6b99583eUL, 0x60975133UL, 0x7d854a24UL, 0x768b4329UL, +0x1fd13462UL, 0x14df3d6fUL, 0x09cd2678UL, 0x02c32f75UL, 0x33e91056UL, 0x38e7195bUL, 0x25f5024cUL, 0x2efb0b41UL, +0x8c9ad761UL, 0x8794de6cUL, 0x9a86c57bUL, 0x9188cc76UL, 0xa0a2f355UL, 0xabacfa58UL, 0xb6bee14fUL, 0xbdb0e842UL, +0xd4ea9f09UL, 0xdfe49604UL, 0xc2f68d13UL, 0xc9f8841eUL, 0xf8d2bb3dUL, 0xf3dcb230UL, 0xeecea927UL, 0xe5c0a02aUL, +0x3c7a47b1UL, 0x37744ebcUL, 0x2a6655abUL, 0x21685ca6UL, 0x10426385UL, 0x1b4c6a88UL, 0x065e719fUL, 0x0d507892UL, +0x640a0fd9UL, 0x6f0406d4UL, 0x72161dc3UL, 0x791814ceUL, 0x48322bedUL, 0x433c22e0UL, 0x5e2e39f7UL, 0x552030faUL, +0x01ec9ab7UL, 0x0ae293baUL, 0x17f088adUL, 0x1cfe81a0UL, 0x2dd4be83UL, 0x26dab78eUL, 0x3bc8ac99UL, 0x30c6a594UL, +0x599cd2dfUL, 0x5292dbd2UL, 0x4f80c0c5UL, 0x448ec9c8UL, 0x75a4f6ebUL, 0x7eaaffe6UL, 0x63b8e4f1UL, 0x68b6edfcUL, +0xb10c0a67UL, 0xba02036aUL, 0xa710187dUL, 0xac1e1170UL, 0x9d342e53UL, 0x963a275eUL, 0x8b283c49UL, 0x80263544UL, +0xe97c420fUL, 0xe2724b02UL, 0xff605015UL, 0xf46e5918UL, 0xc544663bUL, 0xce4a6f36UL, 0xd3587421UL, 0xd8567d2cUL, +0x7a37a10cUL, 0x7139a801UL, 0x6c2bb316UL, 0x6725ba1bUL, 0x560f8538UL, 0x5d018c35UL, 0x40139722UL, 0x4b1d9e2fUL, +0x2247e964UL, 0x2949e069UL, 0x345bfb7eUL, 0x3f55f273UL, 0x0e7fcd50UL, 0x0571c45dUL, 0x1863df4aUL, 0x136dd647UL, +0xcad731dcUL, 0xc1d938d1UL, 0xdccb23c6UL, 0xd7c52acbUL, 0xe6ef15e8UL, 0xede11ce5UL, 0xf0f307f2UL, 0xfbfd0effUL, +0x92a779b4UL, 0x99a970b9UL, 0x84bb6baeUL, 0x8fb562a3UL, 0xbe9f5d80UL, 0xb591548dUL, 0xa8834f9aUL, 0xa38d4697UL +}; + +static const ulong32 Tks2[] = { +0x00000000UL, 0x0d0b0e09UL, 0x1a161c12UL, 0x171d121bUL, 0x342c3824UL, 0x3927362dUL, 0x2e3a2436UL, 0x23312a3fUL, +0x68587048UL, 0x65537e41UL, 0x724e6c5aUL, 0x7f456253UL, 0x5c74486cUL, 0x517f4665UL, 0x4662547eUL, 0x4b695a77UL, +0xd0b0e090UL, 0xddbbee99UL, 0xcaa6fc82UL, 0xc7adf28bUL, 0xe49cd8b4UL, 0xe997d6bdUL, 0xfe8ac4a6UL, 0xf381caafUL, +0xb8e890d8UL, 0xb5e39ed1UL, 0xa2fe8ccaUL, 0xaff582c3UL, 0x8cc4a8fcUL, 0x81cfa6f5UL, 0x96d2b4eeUL, 0x9bd9bae7UL, +0xbb7bdb3bUL, 0xb670d532UL, 0xa16dc729UL, 0xac66c920UL, 0x8f57e31fUL, 0x825ced16UL, 0x9541ff0dUL, 0x984af104UL, +0xd323ab73UL, 0xde28a57aUL, 0xc935b761UL, 0xc43eb968UL, 0xe70f9357UL, 0xea049d5eUL, 0xfd198f45UL, 0xf012814cUL, +0x6bcb3babUL, 0x66c035a2UL, 0x71dd27b9UL, 0x7cd629b0UL, 0x5fe7038fUL, 0x52ec0d86UL, 0x45f11f9dUL, 0x48fa1194UL, +0x03934be3UL, 0x0e9845eaUL, 0x198557f1UL, 0x148e59f8UL, 0x37bf73c7UL, 0x3ab47dceUL, 0x2da96fd5UL, 0x20a261dcUL, +0x6df6ad76UL, 0x60fda37fUL, 0x77e0b164UL, 0x7aebbf6dUL, 0x59da9552UL, 0x54d19b5bUL, 0x43cc8940UL, 0x4ec78749UL, +0x05aedd3eUL, 0x08a5d337UL, 0x1fb8c12cUL, 0x12b3cf25UL, 0x3182e51aUL, 0x3c89eb13UL, 0x2b94f908UL, 0x269ff701UL, +0xbd464de6UL, 0xb04d43efUL, 0xa75051f4UL, 0xaa5b5ffdUL, 0x896a75c2UL, 0x84617bcbUL, 0x937c69d0UL, 0x9e7767d9UL, +0xd51e3daeUL, 0xd81533a7UL, 0xcf0821bcUL, 0xc2032fb5UL, 0xe132058aUL, 0xec390b83UL, 0xfb241998UL, 0xf62f1791UL, +0xd68d764dUL, 0xdb867844UL, 0xcc9b6a5fUL, 0xc1906456UL, 0xe2a14e69UL, 0xefaa4060UL, 0xf8b7527bUL, 0xf5bc5c72UL, +0xbed50605UL, 0xb3de080cUL, 0xa4c31a17UL, 0xa9c8141eUL, 0x8af93e21UL, 0x87f23028UL, 0x90ef2233UL, 0x9de42c3aUL, +0x063d96ddUL, 0x0b3698d4UL, 0x1c2b8acfUL, 0x112084c6UL, 0x3211aef9UL, 0x3f1aa0f0UL, 0x2807b2ebUL, 0x250cbce2UL, +0x6e65e695UL, 0x636ee89cUL, 0x7473fa87UL, 0x7978f48eUL, 0x5a49deb1UL, 0x5742d0b8UL, 0x405fc2a3UL, 0x4d54ccaaUL, +0xdaf741ecUL, 0xd7fc4fe5UL, 0xc0e15dfeUL, 0xcdea53f7UL, 0xeedb79c8UL, 0xe3d077c1UL, 0xf4cd65daUL, 0xf9c66bd3UL, +0xb2af31a4UL, 0xbfa43fadUL, 0xa8b92db6UL, 0xa5b223bfUL, 0x86830980UL, 0x8b880789UL, 0x9c951592UL, 0x919e1b9bUL, +0x0a47a17cUL, 0x074caf75UL, 0x1051bd6eUL, 0x1d5ab367UL, 0x3e6b9958UL, 0x33609751UL, 0x247d854aUL, 0x29768b43UL, +0x621fd134UL, 0x6f14df3dUL, 0x7809cd26UL, 0x7502c32fUL, 0x5633e910UL, 0x5b38e719UL, 0x4c25f502UL, 0x412efb0bUL, +0x618c9ad7UL, 0x6c8794deUL, 0x7b9a86c5UL, 0x769188ccUL, 0x55a0a2f3UL, 0x58abacfaUL, 0x4fb6bee1UL, 0x42bdb0e8UL, +0x09d4ea9fUL, 0x04dfe496UL, 0x13c2f68dUL, 0x1ec9f884UL, 0x3df8d2bbUL, 0x30f3dcb2UL, 0x27eecea9UL, 0x2ae5c0a0UL, +0xb13c7a47UL, 0xbc37744eUL, 0xab2a6655UL, 0xa621685cUL, 0x85104263UL, 0x881b4c6aUL, 0x9f065e71UL, 0x920d5078UL, +0xd9640a0fUL, 0xd46f0406UL, 0xc372161dUL, 0xce791814UL, 0xed48322bUL, 0xe0433c22UL, 0xf75e2e39UL, 0xfa552030UL, +0xb701ec9aUL, 0xba0ae293UL, 0xad17f088UL, 0xa01cfe81UL, 0x832dd4beUL, 0x8e26dab7UL, 0x993bc8acUL, 0x9430c6a5UL, +0xdf599cd2UL, 0xd25292dbUL, 0xc54f80c0UL, 0xc8448ec9UL, 0xeb75a4f6UL, 0xe67eaaffUL, 0xf163b8e4UL, 0xfc68b6edUL, +0x67b10c0aUL, 0x6aba0203UL, 0x7da71018UL, 0x70ac1e11UL, 0x539d342eUL, 0x5e963a27UL, 0x498b283cUL, 0x44802635UL, +0x0fe97c42UL, 0x02e2724bUL, 0x15ff6050UL, 0x18f46e59UL, 0x3bc54466UL, 0x36ce4a6fUL, 0x21d35874UL, 0x2cd8567dUL, +0x0c7a37a1UL, 0x017139a8UL, 0x166c2bb3UL, 0x1b6725baUL, 0x38560f85UL, 0x355d018cUL, 0x22401397UL, 0x2f4b1d9eUL, +0x642247e9UL, 0x692949e0UL, 0x7e345bfbUL, 0x733f55f2UL, 0x500e7fcdUL, 0x5d0571c4UL, 0x4a1863dfUL, 0x47136dd6UL, +0xdccad731UL, 0xd1c1d938UL, 0xc6dccb23UL, 0xcbd7c52aUL, 0xe8e6ef15UL, 0xe5ede11cUL, 0xf2f0f307UL, 0xfffbfd0eUL, +0xb492a779UL, 0xb999a970UL, 0xae84bb6bUL, 0xa38fb562UL, 0x80be9f5dUL, 0x8db59154UL, 0x9aa8834fUL, 0x97a38d46UL +}; + +static const ulong32 Tks3[] = { +0x00000000UL, 0x090d0b0eUL, 0x121a161cUL, 0x1b171d12UL, 0x24342c38UL, 0x2d392736UL, 0x362e3a24UL, 0x3f23312aUL, +0x48685870UL, 0x4165537eUL, 0x5a724e6cUL, 0x537f4562UL, 0x6c5c7448UL, 0x65517f46UL, 0x7e466254UL, 0x774b695aUL, +0x90d0b0e0UL, 0x99ddbbeeUL, 0x82caa6fcUL, 0x8bc7adf2UL, 0xb4e49cd8UL, 0xbde997d6UL, 0xa6fe8ac4UL, 0xaff381caUL, +0xd8b8e890UL, 0xd1b5e39eUL, 0xcaa2fe8cUL, 0xc3aff582UL, 0xfc8cc4a8UL, 0xf581cfa6UL, 0xee96d2b4UL, 0xe79bd9baUL, +0x3bbb7bdbUL, 0x32b670d5UL, 0x29a16dc7UL, 0x20ac66c9UL, 0x1f8f57e3UL, 0x16825cedUL, 0x0d9541ffUL, 0x04984af1UL, +0x73d323abUL, 0x7ade28a5UL, 0x61c935b7UL, 0x68c43eb9UL, 0x57e70f93UL, 0x5eea049dUL, 0x45fd198fUL, 0x4cf01281UL, +0xab6bcb3bUL, 0xa266c035UL, 0xb971dd27UL, 0xb07cd629UL, 0x8f5fe703UL, 0x8652ec0dUL, 0x9d45f11fUL, 0x9448fa11UL, +0xe303934bUL, 0xea0e9845UL, 0xf1198557UL, 0xf8148e59UL, 0xc737bf73UL, 0xce3ab47dUL, 0xd52da96fUL, 0xdc20a261UL, +0x766df6adUL, 0x7f60fda3UL, 0x6477e0b1UL, 0x6d7aebbfUL, 0x5259da95UL, 0x5b54d19bUL, 0x4043cc89UL, 0x494ec787UL, +0x3e05aeddUL, 0x3708a5d3UL, 0x2c1fb8c1UL, 0x2512b3cfUL, 0x1a3182e5UL, 0x133c89ebUL, 0x082b94f9UL, 0x01269ff7UL, +0xe6bd464dUL, 0xefb04d43UL, 0xf4a75051UL, 0xfdaa5b5fUL, 0xc2896a75UL, 0xcb84617bUL, 0xd0937c69UL, 0xd99e7767UL, +0xaed51e3dUL, 0xa7d81533UL, 0xbccf0821UL, 0xb5c2032fUL, 0x8ae13205UL, 0x83ec390bUL, 0x98fb2419UL, 0x91f62f17UL, +0x4dd68d76UL, 0x44db8678UL, 0x5fcc9b6aUL, 0x56c19064UL, 0x69e2a14eUL, 0x60efaa40UL, 0x7bf8b752UL, 0x72f5bc5cUL, +0x05bed506UL, 0x0cb3de08UL, 0x17a4c31aUL, 0x1ea9c814UL, 0x218af93eUL, 0x2887f230UL, 0x3390ef22UL, 0x3a9de42cUL, +0xdd063d96UL, 0xd40b3698UL, 0xcf1c2b8aUL, 0xc6112084UL, 0xf93211aeUL, 0xf03f1aa0UL, 0xeb2807b2UL, 0xe2250cbcUL, +0x956e65e6UL, 0x9c636ee8UL, 0x877473faUL, 0x8e7978f4UL, 0xb15a49deUL, 0xb85742d0UL, 0xa3405fc2UL, 0xaa4d54ccUL, +0xecdaf741UL, 0xe5d7fc4fUL, 0xfec0e15dUL, 0xf7cdea53UL, 0xc8eedb79UL, 0xc1e3d077UL, 0xdaf4cd65UL, 0xd3f9c66bUL, +0xa4b2af31UL, 0xadbfa43fUL, 0xb6a8b92dUL, 0xbfa5b223UL, 0x80868309UL, 0x898b8807UL, 0x929c9515UL, 0x9b919e1bUL, +0x7c0a47a1UL, 0x75074cafUL, 0x6e1051bdUL, 0x671d5ab3UL, 0x583e6b99UL, 0x51336097UL, 0x4a247d85UL, 0x4329768bUL, +0x34621fd1UL, 0x3d6f14dfUL, 0x267809cdUL, 0x2f7502c3UL, 0x105633e9UL, 0x195b38e7UL, 0x024c25f5UL, 0x0b412efbUL, +0xd7618c9aUL, 0xde6c8794UL, 0xc57b9a86UL, 0xcc769188UL, 0xf355a0a2UL, 0xfa58abacUL, 0xe14fb6beUL, 0xe842bdb0UL, +0x9f09d4eaUL, 0x9604dfe4UL, 0x8d13c2f6UL, 0x841ec9f8UL, 0xbb3df8d2UL, 0xb230f3dcUL, 0xa927eeceUL, 0xa02ae5c0UL, +0x47b13c7aUL, 0x4ebc3774UL, 0x55ab2a66UL, 0x5ca62168UL, 0x63851042UL, 0x6a881b4cUL, 0x719f065eUL, 0x78920d50UL, +0x0fd9640aUL, 0x06d46f04UL, 0x1dc37216UL, 0x14ce7918UL, 0x2bed4832UL, 0x22e0433cUL, 0x39f75e2eUL, 0x30fa5520UL, +0x9ab701ecUL, 0x93ba0ae2UL, 0x88ad17f0UL, 0x81a01cfeUL, 0xbe832dd4UL, 0xb78e26daUL, 0xac993bc8UL, 0xa59430c6UL, +0xd2df599cUL, 0xdbd25292UL, 0xc0c54f80UL, 0xc9c8448eUL, 0xf6eb75a4UL, 0xffe67eaaUL, 0xe4f163b8UL, 0xedfc68b6UL, +0x0a67b10cUL, 0x036aba02UL, 0x187da710UL, 0x1170ac1eUL, 0x2e539d34UL, 0x275e963aUL, 0x3c498b28UL, 0x35448026UL, +0x420fe97cUL, 0x4b02e272UL, 0x5015ff60UL, 0x5918f46eUL, 0x663bc544UL, 0x6f36ce4aUL, 0x7421d358UL, 0x7d2cd856UL, +0xa10c7a37UL, 0xa8017139UL, 0xb3166c2bUL, 0xba1b6725UL, 0x8538560fUL, 0x8c355d01UL, 0x97224013UL, 0x9e2f4b1dUL, +0xe9642247UL, 0xe0692949UL, 0xfb7e345bUL, 0xf2733f55UL, 0xcd500e7fUL, 0xc45d0571UL, 0xdf4a1863UL, 0xd647136dUL, +0x31dccad7UL, 0x38d1c1d9UL, 0x23c6dccbUL, 0x2acbd7c5UL, 0x15e8e6efUL, 0x1ce5ede1UL, 0x07f2f0f3UL, 0x0efffbfdUL, +0x79b492a7UL, 0x70b999a9UL, 0x6bae84bbUL, 0x62a38fb5UL, 0x5d80be9fUL, 0x548db591UL, 0x4f9aa883UL, 0x4697a38dUL +}; + +#endif /* ENCRYPT_ONLY */ + +#endif /* SMALL CODE */ + +static const ulong32 rcon[] = { + 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, + 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL, + 0x1B000000UL, 0x36000000UL, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; + +/* $Source: /cvs/libtom/libtomcrypt/src/ciphers/aes/aes_tab.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:23 $ */ diff --git a/core/lib/libtomcrypt/src/ciphers/des.c b/core/lib/libtomcrypt/src/ciphers/des.c new file mode 100644 index 00000000000..a5bbb29fd12 --- /dev/null +++ b/core/lib/libtomcrypt/src/ciphers/des.c @@ -0,0 +1,1929 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file des.c + LTC_DES code submitted by Dobes Vandermeer +*/ + +#ifdef LTC_DES + +#define EN0 0 +#define DE1 1 + +const struct ltc_cipher_descriptor des_desc = +{ + "des", + 13, + 8, 8, 8, 16, + &des_setup, + &des_ecb_encrypt, + &des_ecb_decrypt, + &des_test, + &des_done, + &des_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +const struct ltc_cipher_descriptor des3_desc = +{ + "3des", + 14, + 24, 24, 8, 16, + &des3_setup, + &des3_ecb_encrypt, + &des3_ecb_decrypt, + &des3_test, + &des3_done, + &des3_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +static const ulong32 bytebit[8] = +{ + 0200, 0100, 040, 020, 010, 04, 02, 01 +}; + +static const ulong32 bigbyte[24] = +{ + 0x800000UL, 0x400000UL, 0x200000UL, 0x100000UL, + 0x80000UL, 0x40000UL, 0x20000UL, 0x10000UL, + 0x8000UL, 0x4000UL, 0x2000UL, 0x1000UL, + 0x800UL, 0x400UL, 0x200UL, 0x100UL, + 0x80UL, 0x40UL, 0x20UL, 0x10UL, + 0x8UL, 0x4UL, 0x2UL, 0x1L +}; + +/* Use the key schedule specific in the standard (ANSI X3.92-1981) */ + +static const unsigned char pc1[56] = { + 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, + 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, + 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, + 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 +}; + +static const unsigned char totrot[16] = { + 1, 2, 4, 6, + 8, 10, 12, 14, + 15, 17, 19, 21, + 23, 25, 27, 28 +}; + +static const unsigned char pc2[48] = { + 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, + 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, + 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, + 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 +}; + + +static const ulong32 SP1[64] = +{ + 0x01010400UL, 0x00000000UL, 0x00010000UL, 0x01010404UL, + 0x01010004UL, 0x00010404UL, 0x00000004UL, 0x00010000UL, + 0x00000400UL, 0x01010400UL, 0x01010404UL, 0x00000400UL, + 0x01000404UL, 0x01010004UL, 0x01000000UL, 0x00000004UL, + 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00010400UL, + 0x00010400UL, 0x01010000UL, 0x01010000UL, 0x01000404UL, + 0x00010004UL, 0x01000004UL, 0x01000004UL, 0x00010004UL, + 0x00000000UL, 0x00000404UL, 0x00010404UL, 0x01000000UL, + 0x00010000UL, 0x01010404UL, 0x00000004UL, 0x01010000UL, + 0x01010400UL, 0x01000000UL, 0x01000000UL, 0x00000400UL, + 0x01010004UL, 0x00010000UL, 0x00010400UL, 0x01000004UL, + 0x00000400UL, 0x00000004UL, 0x01000404UL, 0x00010404UL, + 0x01010404UL, 0x00010004UL, 0x01010000UL, 0x01000404UL, + 0x01000004UL, 0x00000404UL, 0x00010404UL, 0x01010400UL, + 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00000000UL, + 0x00010004UL, 0x00010400UL, 0x00000000UL, 0x01010004UL +}; + +static const ulong32 SP2[64] = +{ + 0x80108020UL, 0x80008000UL, 0x00008000UL, 0x00108020UL, + 0x00100000UL, 0x00000020UL, 0x80100020UL, 0x80008020UL, + 0x80000020UL, 0x80108020UL, 0x80108000UL, 0x80000000UL, + 0x80008000UL, 0x00100000UL, 0x00000020UL, 0x80100020UL, + 0x00108000UL, 0x00100020UL, 0x80008020UL, 0x00000000UL, + 0x80000000UL, 0x00008000UL, 0x00108020UL, 0x80100000UL, + 0x00100020UL, 0x80000020UL, 0x00000000UL, 0x00108000UL, + 0x00008020UL, 0x80108000UL, 0x80100000UL, 0x00008020UL, + 0x00000000UL, 0x00108020UL, 0x80100020UL, 0x00100000UL, + 0x80008020UL, 0x80100000UL, 0x80108000UL, 0x00008000UL, + 0x80100000UL, 0x80008000UL, 0x00000020UL, 0x80108020UL, + 0x00108020UL, 0x00000020UL, 0x00008000UL, 0x80000000UL, + 0x00008020UL, 0x80108000UL, 0x00100000UL, 0x80000020UL, + 0x00100020UL, 0x80008020UL, 0x80000020UL, 0x00100020UL, + 0x00108000UL, 0x00000000UL, 0x80008000UL, 0x00008020UL, + 0x80000000UL, 0x80100020UL, 0x80108020UL, 0x00108000UL +}; + +static const ulong32 SP3[64] = +{ + 0x00000208UL, 0x08020200UL, 0x00000000UL, 0x08020008UL, + 0x08000200UL, 0x00000000UL, 0x00020208UL, 0x08000200UL, + 0x00020008UL, 0x08000008UL, 0x08000008UL, 0x00020000UL, + 0x08020208UL, 0x00020008UL, 0x08020000UL, 0x00000208UL, + 0x08000000UL, 0x00000008UL, 0x08020200UL, 0x00000200UL, + 0x00020200UL, 0x08020000UL, 0x08020008UL, 0x00020208UL, + 0x08000208UL, 0x00020200UL, 0x00020000UL, 0x08000208UL, + 0x00000008UL, 0x08020208UL, 0x00000200UL, 0x08000000UL, + 0x08020200UL, 0x08000000UL, 0x00020008UL, 0x00000208UL, + 0x00020000UL, 0x08020200UL, 0x08000200UL, 0x00000000UL, + 0x00000200UL, 0x00020008UL, 0x08020208UL, 0x08000200UL, + 0x08000008UL, 0x00000200UL, 0x00000000UL, 0x08020008UL, + 0x08000208UL, 0x00020000UL, 0x08000000UL, 0x08020208UL, + 0x00000008UL, 0x00020208UL, 0x00020200UL, 0x08000008UL, + 0x08020000UL, 0x08000208UL, 0x00000208UL, 0x08020000UL, + 0x00020208UL, 0x00000008UL, 0x08020008UL, 0x00020200UL +}; + +static const ulong32 SP4[64] = +{ + 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL, + 0x00802080UL, 0x00800081UL, 0x00800001UL, 0x00002001UL, + 0x00000000UL, 0x00802000UL, 0x00802000UL, 0x00802081UL, + 0x00000081UL, 0x00000000UL, 0x00800080UL, 0x00800001UL, + 0x00000001UL, 0x00002000UL, 0x00800000UL, 0x00802001UL, + 0x00000080UL, 0x00800000UL, 0x00002001UL, 0x00002080UL, + 0x00800081UL, 0x00000001UL, 0x00002080UL, 0x00800080UL, + 0x00002000UL, 0x00802080UL, 0x00802081UL, 0x00000081UL, + 0x00800080UL, 0x00800001UL, 0x00802000UL, 0x00802081UL, + 0x00000081UL, 0x00000000UL, 0x00000000UL, 0x00802000UL, + 0x00002080UL, 0x00800080UL, 0x00800081UL, 0x00000001UL, + 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL, + 0x00802081UL, 0x00000081UL, 0x00000001UL, 0x00002000UL, + 0x00800001UL, 0x00002001UL, 0x00802080UL, 0x00800081UL, + 0x00002001UL, 0x00002080UL, 0x00800000UL, 0x00802001UL, + 0x00000080UL, 0x00800000UL, 0x00002000UL, 0x00802080UL +}; + +static const ulong32 SP5[64] = +{ + 0x00000100UL, 0x02080100UL, 0x02080000UL, 0x42000100UL, + 0x00080000UL, 0x00000100UL, 0x40000000UL, 0x02080000UL, + 0x40080100UL, 0x00080000UL, 0x02000100UL, 0x40080100UL, + 0x42000100UL, 0x42080000UL, 0x00080100UL, 0x40000000UL, + 0x02000000UL, 0x40080000UL, 0x40080000UL, 0x00000000UL, + 0x40000100UL, 0x42080100UL, 0x42080100UL, 0x02000100UL, + 0x42080000UL, 0x40000100UL, 0x00000000UL, 0x42000000UL, + 0x02080100UL, 0x02000000UL, 0x42000000UL, 0x00080100UL, + 0x00080000UL, 0x42000100UL, 0x00000100UL, 0x02000000UL, + 0x40000000UL, 0x02080000UL, 0x42000100UL, 0x40080100UL, + 0x02000100UL, 0x40000000UL, 0x42080000UL, 0x02080100UL, + 0x40080100UL, 0x00000100UL, 0x02000000UL, 0x42080000UL, + 0x42080100UL, 0x00080100UL, 0x42000000UL, 0x42080100UL, + 0x02080000UL, 0x00000000UL, 0x40080000UL, 0x42000000UL, + 0x00080100UL, 0x02000100UL, 0x40000100UL, 0x00080000UL, + 0x00000000UL, 0x40080000UL, 0x02080100UL, 0x40000100UL +}; + +static const ulong32 SP6[64] = +{ + 0x20000010UL, 0x20400000UL, 0x00004000UL, 0x20404010UL, + 0x20400000UL, 0x00000010UL, 0x20404010UL, 0x00400000UL, + 0x20004000UL, 0x00404010UL, 0x00400000UL, 0x20000010UL, + 0x00400010UL, 0x20004000UL, 0x20000000UL, 0x00004010UL, + 0x00000000UL, 0x00400010UL, 0x20004010UL, 0x00004000UL, + 0x00404000UL, 0x20004010UL, 0x00000010UL, 0x20400010UL, + 0x20400010UL, 0x00000000UL, 0x00404010UL, 0x20404000UL, + 0x00004010UL, 0x00404000UL, 0x20404000UL, 0x20000000UL, + 0x20004000UL, 0x00000010UL, 0x20400010UL, 0x00404000UL, + 0x20404010UL, 0x00400000UL, 0x00004010UL, 0x20000010UL, + 0x00400000UL, 0x20004000UL, 0x20000000UL, 0x00004010UL, + 0x20000010UL, 0x20404010UL, 0x00404000UL, 0x20400000UL, + 0x00404010UL, 0x20404000UL, 0x00000000UL, 0x20400010UL, + 0x00000010UL, 0x00004000UL, 0x20400000UL, 0x00404010UL, + 0x00004000UL, 0x00400010UL, 0x20004010UL, 0x00000000UL, + 0x20404000UL, 0x20000000UL, 0x00400010UL, 0x20004010UL +}; + +static const ulong32 SP7[64] = +{ + 0x00200000UL, 0x04200002UL, 0x04000802UL, 0x00000000UL, + 0x00000800UL, 0x04000802UL, 0x00200802UL, 0x04200800UL, + 0x04200802UL, 0x00200000UL, 0x00000000UL, 0x04000002UL, + 0x00000002UL, 0x04000000UL, 0x04200002UL, 0x00000802UL, + 0x04000800UL, 0x00200802UL, 0x00200002UL, 0x04000800UL, + 0x04000002UL, 0x04200000UL, 0x04200800UL, 0x00200002UL, + 0x04200000UL, 0x00000800UL, 0x00000802UL, 0x04200802UL, + 0x00200800UL, 0x00000002UL, 0x04000000UL, 0x00200800UL, + 0x04000000UL, 0x00200800UL, 0x00200000UL, 0x04000802UL, + 0x04000802UL, 0x04200002UL, 0x04200002UL, 0x00000002UL, + 0x00200002UL, 0x04000000UL, 0x04000800UL, 0x00200000UL, + 0x04200800UL, 0x00000802UL, 0x00200802UL, 0x04200800UL, + 0x00000802UL, 0x04000002UL, 0x04200802UL, 0x04200000UL, + 0x00200800UL, 0x00000000UL, 0x00000002UL, 0x04200802UL, + 0x00000000UL, 0x00200802UL, 0x04200000UL, 0x00000800UL, + 0x04000002UL, 0x04000800UL, 0x00000800UL, 0x00200002UL +}; + +static const ulong32 SP8[64] = +{ + 0x10001040UL, 0x00001000UL, 0x00040000UL, 0x10041040UL, + 0x10000000UL, 0x10001040UL, 0x00000040UL, 0x10000000UL, + 0x00040040UL, 0x10040000UL, 0x10041040UL, 0x00041000UL, + 0x10041000UL, 0x00041040UL, 0x00001000UL, 0x00000040UL, + 0x10040000UL, 0x10000040UL, 0x10001000UL, 0x00001040UL, + 0x00041000UL, 0x00040040UL, 0x10040040UL, 0x10041000UL, + 0x00001040UL, 0x00000000UL, 0x00000000UL, 0x10040040UL, + 0x10000040UL, 0x10001000UL, 0x00041040UL, 0x00040000UL, + 0x00041040UL, 0x00040000UL, 0x10041000UL, 0x00001000UL, + 0x00000040UL, 0x10040040UL, 0x00001000UL, 0x00041040UL, + 0x10001000UL, 0x00000040UL, 0x10000040UL, 0x10040000UL, + 0x10040040UL, 0x10000000UL, 0x00040000UL, 0x10001040UL, + 0x00000000UL, 0x10041040UL, 0x00040040UL, 0x10000040UL, + 0x10040000UL, 0x10001000UL, 0x10001040UL, 0x00000000UL, + 0x10041040UL, 0x00041000UL, 0x00041000UL, 0x00001040UL, + 0x00001040UL, 0x00040040UL, 0x10000000UL, 0x10041000UL +}; + +#ifndef LTC_SMALL_CODE + +static const ulong64 des_ip[8][256] = { + +{ CONST64(0x0000000000000000), CONST64(0x0000001000000000), CONST64(0x0000000000000010), CONST64(0x0000001000000010), + CONST64(0x0000100000000000), CONST64(0x0000101000000000), CONST64(0x0000100000000010), CONST64(0x0000101000000010), + CONST64(0x0000000000001000), CONST64(0x0000001000001000), CONST64(0x0000000000001010), CONST64(0x0000001000001010), + CONST64(0x0000100000001000), CONST64(0x0000101000001000), CONST64(0x0000100000001010), CONST64(0x0000101000001010), + CONST64(0x0010000000000000), CONST64(0x0010001000000000), CONST64(0x0010000000000010), CONST64(0x0010001000000010), + CONST64(0x0010100000000000), CONST64(0x0010101000000000), CONST64(0x0010100000000010), CONST64(0x0010101000000010), + CONST64(0x0010000000001000), CONST64(0x0010001000001000), CONST64(0x0010000000001010), CONST64(0x0010001000001010), + CONST64(0x0010100000001000), CONST64(0x0010101000001000), CONST64(0x0010100000001010), CONST64(0x0010101000001010), + CONST64(0x0000000000100000), CONST64(0x0000001000100000), CONST64(0x0000000000100010), CONST64(0x0000001000100010), + CONST64(0x0000100000100000), CONST64(0x0000101000100000), CONST64(0x0000100000100010), CONST64(0x0000101000100010), + CONST64(0x0000000000101000), CONST64(0x0000001000101000), CONST64(0x0000000000101010), CONST64(0x0000001000101010), + CONST64(0x0000100000101000), CONST64(0x0000101000101000), CONST64(0x0000100000101010), CONST64(0x0000101000101010), + CONST64(0x0010000000100000), CONST64(0x0010001000100000), CONST64(0x0010000000100010), CONST64(0x0010001000100010), + CONST64(0x0010100000100000), CONST64(0x0010101000100000), CONST64(0x0010100000100010), CONST64(0x0010101000100010), + CONST64(0x0010000000101000), CONST64(0x0010001000101000), CONST64(0x0010000000101010), CONST64(0x0010001000101010), + CONST64(0x0010100000101000), CONST64(0x0010101000101000), CONST64(0x0010100000101010), CONST64(0x0010101000101010), + CONST64(0x1000000000000000), CONST64(0x1000001000000000), CONST64(0x1000000000000010), CONST64(0x1000001000000010), + CONST64(0x1000100000000000), CONST64(0x1000101000000000), CONST64(0x1000100000000010), CONST64(0x1000101000000010), + CONST64(0x1000000000001000), CONST64(0x1000001000001000), CONST64(0x1000000000001010), CONST64(0x1000001000001010), + CONST64(0x1000100000001000), CONST64(0x1000101000001000), CONST64(0x1000100000001010), CONST64(0x1000101000001010), + CONST64(0x1010000000000000), CONST64(0x1010001000000000), CONST64(0x1010000000000010), CONST64(0x1010001000000010), + CONST64(0x1010100000000000), CONST64(0x1010101000000000), CONST64(0x1010100000000010), CONST64(0x1010101000000010), + CONST64(0x1010000000001000), CONST64(0x1010001000001000), CONST64(0x1010000000001010), CONST64(0x1010001000001010), + CONST64(0x1010100000001000), CONST64(0x1010101000001000), CONST64(0x1010100000001010), CONST64(0x1010101000001010), + CONST64(0x1000000000100000), CONST64(0x1000001000100000), CONST64(0x1000000000100010), CONST64(0x1000001000100010), + CONST64(0x1000100000100000), CONST64(0x1000101000100000), CONST64(0x1000100000100010), CONST64(0x1000101000100010), + CONST64(0x1000000000101000), CONST64(0x1000001000101000), CONST64(0x1000000000101010), CONST64(0x1000001000101010), + CONST64(0x1000100000101000), CONST64(0x1000101000101000), CONST64(0x1000100000101010), CONST64(0x1000101000101010), + CONST64(0x1010000000100000), CONST64(0x1010001000100000), CONST64(0x1010000000100010), CONST64(0x1010001000100010), + CONST64(0x1010100000100000), CONST64(0x1010101000100000), CONST64(0x1010100000100010), CONST64(0x1010101000100010), + CONST64(0x1010000000101000), CONST64(0x1010001000101000), CONST64(0x1010000000101010), CONST64(0x1010001000101010), + CONST64(0x1010100000101000), CONST64(0x1010101000101000), CONST64(0x1010100000101010), CONST64(0x1010101000101010), + CONST64(0x0000000010000000), CONST64(0x0000001010000000), CONST64(0x0000000010000010), CONST64(0x0000001010000010), + CONST64(0x0000100010000000), CONST64(0x0000101010000000), CONST64(0x0000100010000010), CONST64(0x0000101010000010), + CONST64(0x0000000010001000), CONST64(0x0000001010001000), CONST64(0x0000000010001010), CONST64(0x0000001010001010), + CONST64(0x0000100010001000), CONST64(0x0000101010001000), CONST64(0x0000100010001010), CONST64(0x0000101010001010), + CONST64(0x0010000010000000), CONST64(0x0010001010000000), CONST64(0x0010000010000010), CONST64(0x0010001010000010), + CONST64(0x0010100010000000), CONST64(0x0010101010000000), CONST64(0x0010100010000010), CONST64(0x0010101010000010), + CONST64(0x0010000010001000), CONST64(0x0010001010001000), CONST64(0x0010000010001010), CONST64(0x0010001010001010), + CONST64(0x0010100010001000), CONST64(0x0010101010001000), CONST64(0x0010100010001010), CONST64(0x0010101010001010), + CONST64(0x0000000010100000), CONST64(0x0000001010100000), CONST64(0x0000000010100010), CONST64(0x0000001010100010), + CONST64(0x0000100010100000), CONST64(0x0000101010100000), CONST64(0x0000100010100010), CONST64(0x0000101010100010), + CONST64(0x0000000010101000), CONST64(0x0000001010101000), CONST64(0x0000000010101010), CONST64(0x0000001010101010), + CONST64(0x0000100010101000), CONST64(0x0000101010101000), CONST64(0x0000100010101010), CONST64(0x0000101010101010), + CONST64(0x0010000010100000), CONST64(0x0010001010100000), CONST64(0x0010000010100010), CONST64(0x0010001010100010), + CONST64(0x0010100010100000), CONST64(0x0010101010100000), CONST64(0x0010100010100010), CONST64(0x0010101010100010), + CONST64(0x0010000010101000), CONST64(0x0010001010101000), CONST64(0x0010000010101010), CONST64(0x0010001010101010), + CONST64(0x0010100010101000), CONST64(0x0010101010101000), CONST64(0x0010100010101010), CONST64(0x0010101010101010), + CONST64(0x1000000010000000), CONST64(0x1000001010000000), CONST64(0x1000000010000010), CONST64(0x1000001010000010), + CONST64(0x1000100010000000), CONST64(0x1000101010000000), CONST64(0x1000100010000010), CONST64(0x1000101010000010), + CONST64(0x1000000010001000), CONST64(0x1000001010001000), CONST64(0x1000000010001010), CONST64(0x1000001010001010), + CONST64(0x1000100010001000), CONST64(0x1000101010001000), CONST64(0x1000100010001010), CONST64(0x1000101010001010), + CONST64(0x1010000010000000), CONST64(0x1010001010000000), CONST64(0x1010000010000010), CONST64(0x1010001010000010), + CONST64(0x1010100010000000), CONST64(0x1010101010000000), CONST64(0x1010100010000010), CONST64(0x1010101010000010), + CONST64(0x1010000010001000), CONST64(0x1010001010001000), CONST64(0x1010000010001010), CONST64(0x1010001010001010), + CONST64(0x1010100010001000), CONST64(0x1010101010001000), CONST64(0x1010100010001010), CONST64(0x1010101010001010), + CONST64(0x1000000010100000), CONST64(0x1000001010100000), CONST64(0x1000000010100010), CONST64(0x1000001010100010), + CONST64(0x1000100010100000), CONST64(0x1000101010100000), CONST64(0x1000100010100010), CONST64(0x1000101010100010), + CONST64(0x1000000010101000), CONST64(0x1000001010101000), CONST64(0x1000000010101010), CONST64(0x1000001010101010), + CONST64(0x1000100010101000), CONST64(0x1000101010101000), CONST64(0x1000100010101010), CONST64(0x1000101010101010), + CONST64(0x1010000010100000), CONST64(0x1010001010100000), CONST64(0x1010000010100010), CONST64(0x1010001010100010), + CONST64(0x1010100010100000), CONST64(0x1010101010100000), CONST64(0x1010100010100010), CONST64(0x1010101010100010), + CONST64(0x1010000010101000), CONST64(0x1010001010101000), CONST64(0x1010000010101010), CONST64(0x1010001010101010), + CONST64(0x1010100010101000), CONST64(0x1010101010101000), CONST64(0x1010100010101010), CONST64(0x1010101010101010) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000000800000000), CONST64(0x0000000000000008), CONST64(0x0000000800000008), + CONST64(0x0000080000000000), CONST64(0x0000080800000000), CONST64(0x0000080000000008), CONST64(0x0000080800000008), + CONST64(0x0000000000000800), CONST64(0x0000000800000800), CONST64(0x0000000000000808), CONST64(0x0000000800000808), + CONST64(0x0000080000000800), CONST64(0x0000080800000800), CONST64(0x0000080000000808), CONST64(0x0000080800000808), + CONST64(0x0008000000000000), CONST64(0x0008000800000000), CONST64(0x0008000000000008), CONST64(0x0008000800000008), + CONST64(0x0008080000000000), CONST64(0x0008080800000000), CONST64(0x0008080000000008), CONST64(0x0008080800000008), + CONST64(0x0008000000000800), CONST64(0x0008000800000800), CONST64(0x0008000000000808), CONST64(0x0008000800000808), + CONST64(0x0008080000000800), CONST64(0x0008080800000800), CONST64(0x0008080000000808), CONST64(0x0008080800000808), + CONST64(0x0000000000080000), CONST64(0x0000000800080000), CONST64(0x0000000000080008), CONST64(0x0000000800080008), + CONST64(0x0000080000080000), CONST64(0x0000080800080000), CONST64(0x0000080000080008), CONST64(0x0000080800080008), + CONST64(0x0000000000080800), CONST64(0x0000000800080800), CONST64(0x0000000000080808), CONST64(0x0000000800080808), + CONST64(0x0000080000080800), CONST64(0x0000080800080800), CONST64(0x0000080000080808), CONST64(0x0000080800080808), + CONST64(0x0008000000080000), CONST64(0x0008000800080000), CONST64(0x0008000000080008), CONST64(0x0008000800080008), + CONST64(0x0008080000080000), CONST64(0x0008080800080000), CONST64(0x0008080000080008), CONST64(0x0008080800080008), + CONST64(0x0008000000080800), CONST64(0x0008000800080800), CONST64(0x0008000000080808), CONST64(0x0008000800080808), + CONST64(0x0008080000080800), CONST64(0x0008080800080800), CONST64(0x0008080000080808), CONST64(0x0008080800080808), + CONST64(0x0800000000000000), CONST64(0x0800000800000000), CONST64(0x0800000000000008), CONST64(0x0800000800000008), + CONST64(0x0800080000000000), CONST64(0x0800080800000000), CONST64(0x0800080000000008), CONST64(0x0800080800000008), + CONST64(0x0800000000000800), CONST64(0x0800000800000800), CONST64(0x0800000000000808), CONST64(0x0800000800000808), + CONST64(0x0800080000000800), CONST64(0x0800080800000800), CONST64(0x0800080000000808), CONST64(0x0800080800000808), + CONST64(0x0808000000000000), CONST64(0x0808000800000000), CONST64(0x0808000000000008), CONST64(0x0808000800000008), + CONST64(0x0808080000000000), CONST64(0x0808080800000000), CONST64(0x0808080000000008), CONST64(0x0808080800000008), + CONST64(0x0808000000000800), CONST64(0x0808000800000800), CONST64(0x0808000000000808), CONST64(0x0808000800000808), + CONST64(0x0808080000000800), CONST64(0x0808080800000800), CONST64(0x0808080000000808), CONST64(0x0808080800000808), + CONST64(0x0800000000080000), CONST64(0x0800000800080000), CONST64(0x0800000000080008), CONST64(0x0800000800080008), + CONST64(0x0800080000080000), CONST64(0x0800080800080000), CONST64(0x0800080000080008), CONST64(0x0800080800080008), + CONST64(0x0800000000080800), CONST64(0x0800000800080800), CONST64(0x0800000000080808), CONST64(0x0800000800080808), + CONST64(0x0800080000080800), CONST64(0x0800080800080800), CONST64(0x0800080000080808), CONST64(0x0800080800080808), + CONST64(0x0808000000080000), CONST64(0x0808000800080000), CONST64(0x0808000000080008), CONST64(0x0808000800080008), + CONST64(0x0808080000080000), CONST64(0x0808080800080000), CONST64(0x0808080000080008), CONST64(0x0808080800080008), + CONST64(0x0808000000080800), CONST64(0x0808000800080800), CONST64(0x0808000000080808), CONST64(0x0808000800080808), + CONST64(0x0808080000080800), CONST64(0x0808080800080800), CONST64(0x0808080000080808), CONST64(0x0808080800080808), + CONST64(0x0000000008000000), CONST64(0x0000000808000000), CONST64(0x0000000008000008), CONST64(0x0000000808000008), + CONST64(0x0000080008000000), CONST64(0x0000080808000000), CONST64(0x0000080008000008), CONST64(0x0000080808000008), + CONST64(0x0000000008000800), CONST64(0x0000000808000800), CONST64(0x0000000008000808), CONST64(0x0000000808000808), + CONST64(0x0000080008000800), CONST64(0x0000080808000800), CONST64(0x0000080008000808), CONST64(0x0000080808000808), + CONST64(0x0008000008000000), CONST64(0x0008000808000000), CONST64(0x0008000008000008), CONST64(0x0008000808000008), + CONST64(0x0008080008000000), CONST64(0x0008080808000000), CONST64(0x0008080008000008), CONST64(0x0008080808000008), + CONST64(0x0008000008000800), CONST64(0x0008000808000800), CONST64(0x0008000008000808), CONST64(0x0008000808000808), + CONST64(0x0008080008000800), CONST64(0x0008080808000800), CONST64(0x0008080008000808), CONST64(0x0008080808000808), + CONST64(0x0000000008080000), CONST64(0x0000000808080000), CONST64(0x0000000008080008), CONST64(0x0000000808080008), + CONST64(0x0000080008080000), CONST64(0x0000080808080000), CONST64(0x0000080008080008), CONST64(0x0000080808080008), + CONST64(0x0000000008080800), CONST64(0x0000000808080800), CONST64(0x0000000008080808), CONST64(0x0000000808080808), + CONST64(0x0000080008080800), CONST64(0x0000080808080800), CONST64(0x0000080008080808), CONST64(0x0000080808080808), + CONST64(0x0008000008080000), CONST64(0x0008000808080000), CONST64(0x0008000008080008), CONST64(0x0008000808080008), + CONST64(0x0008080008080000), CONST64(0x0008080808080000), CONST64(0x0008080008080008), CONST64(0x0008080808080008), + CONST64(0x0008000008080800), CONST64(0x0008000808080800), CONST64(0x0008000008080808), CONST64(0x0008000808080808), + CONST64(0x0008080008080800), CONST64(0x0008080808080800), CONST64(0x0008080008080808), CONST64(0x0008080808080808), + CONST64(0x0800000008000000), CONST64(0x0800000808000000), CONST64(0x0800000008000008), CONST64(0x0800000808000008), + CONST64(0x0800080008000000), CONST64(0x0800080808000000), CONST64(0x0800080008000008), CONST64(0x0800080808000008), + CONST64(0x0800000008000800), CONST64(0x0800000808000800), CONST64(0x0800000008000808), CONST64(0x0800000808000808), + CONST64(0x0800080008000800), CONST64(0x0800080808000800), CONST64(0x0800080008000808), CONST64(0x0800080808000808), + CONST64(0x0808000008000000), CONST64(0x0808000808000000), CONST64(0x0808000008000008), CONST64(0x0808000808000008), + CONST64(0x0808080008000000), CONST64(0x0808080808000000), CONST64(0x0808080008000008), CONST64(0x0808080808000008), + CONST64(0x0808000008000800), CONST64(0x0808000808000800), CONST64(0x0808000008000808), CONST64(0x0808000808000808), + CONST64(0x0808080008000800), CONST64(0x0808080808000800), CONST64(0x0808080008000808), CONST64(0x0808080808000808), + CONST64(0x0800000008080000), CONST64(0x0800000808080000), CONST64(0x0800000008080008), CONST64(0x0800000808080008), + CONST64(0x0800080008080000), CONST64(0x0800080808080000), CONST64(0x0800080008080008), CONST64(0x0800080808080008), + CONST64(0x0800000008080800), CONST64(0x0800000808080800), CONST64(0x0800000008080808), CONST64(0x0800000808080808), + CONST64(0x0800080008080800), CONST64(0x0800080808080800), CONST64(0x0800080008080808), CONST64(0x0800080808080808), + CONST64(0x0808000008080000), CONST64(0x0808000808080000), CONST64(0x0808000008080008), CONST64(0x0808000808080008), + CONST64(0x0808080008080000), CONST64(0x0808080808080000), CONST64(0x0808080008080008), CONST64(0x0808080808080008), + CONST64(0x0808000008080800), CONST64(0x0808000808080800), CONST64(0x0808000008080808), CONST64(0x0808000808080808), + CONST64(0x0808080008080800), CONST64(0x0808080808080800), CONST64(0x0808080008080808), CONST64(0x0808080808080808) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000000400000000), CONST64(0x0000000000000004), CONST64(0x0000000400000004), + CONST64(0x0000040000000000), CONST64(0x0000040400000000), CONST64(0x0000040000000004), CONST64(0x0000040400000004), + CONST64(0x0000000000000400), CONST64(0x0000000400000400), CONST64(0x0000000000000404), CONST64(0x0000000400000404), + CONST64(0x0000040000000400), CONST64(0x0000040400000400), CONST64(0x0000040000000404), CONST64(0x0000040400000404), + CONST64(0x0004000000000000), CONST64(0x0004000400000000), CONST64(0x0004000000000004), CONST64(0x0004000400000004), + CONST64(0x0004040000000000), CONST64(0x0004040400000000), CONST64(0x0004040000000004), CONST64(0x0004040400000004), + CONST64(0x0004000000000400), CONST64(0x0004000400000400), CONST64(0x0004000000000404), CONST64(0x0004000400000404), + CONST64(0x0004040000000400), CONST64(0x0004040400000400), CONST64(0x0004040000000404), CONST64(0x0004040400000404), + CONST64(0x0000000000040000), CONST64(0x0000000400040000), CONST64(0x0000000000040004), CONST64(0x0000000400040004), + CONST64(0x0000040000040000), CONST64(0x0000040400040000), CONST64(0x0000040000040004), CONST64(0x0000040400040004), + CONST64(0x0000000000040400), CONST64(0x0000000400040400), CONST64(0x0000000000040404), CONST64(0x0000000400040404), + CONST64(0x0000040000040400), CONST64(0x0000040400040400), CONST64(0x0000040000040404), CONST64(0x0000040400040404), + CONST64(0x0004000000040000), CONST64(0x0004000400040000), CONST64(0x0004000000040004), CONST64(0x0004000400040004), + CONST64(0x0004040000040000), CONST64(0x0004040400040000), CONST64(0x0004040000040004), CONST64(0x0004040400040004), + CONST64(0x0004000000040400), CONST64(0x0004000400040400), CONST64(0x0004000000040404), CONST64(0x0004000400040404), + CONST64(0x0004040000040400), CONST64(0x0004040400040400), CONST64(0x0004040000040404), CONST64(0x0004040400040404), + CONST64(0x0400000000000000), CONST64(0x0400000400000000), CONST64(0x0400000000000004), CONST64(0x0400000400000004), + CONST64(0x0400040000000000), CONST64(0x0400040400000000), CONST64(0x0400040000000004), CONST64(0x0400040400000004), + CONST64(0x0400000000000400), CONST64(0x0400000400000400), CONST64(0x0400000000000404), CONST64(0x0400000400000404), + CONST64(0x0400040000000400), CONST64(0x0400040400000400), CONST64(0x0400040000000404), CONST64(0x0400040400000404), + CONST64(0x0404000000000000), CONST64(0x0404000400000000), CONST64(0x0404000000000004), CONST64(0x0404000400000004), + CONST64(0x0404040000000000), CONST64(0x0404040400000000), CONST64(0x0404040000000004), CONST64(0x0404040400000004), + CONST64(0x0404000000000400), CONST64(0x0404000400000400), CONST64(0x0404000000000404), CONST64(0x0404000400000404), + CONST64(0x0404040000000400), CONST64(0x0404040400000400), CONST64(0x0404040000000404), CONST64(0x0404040400000404), + CONST64(0x0400000000040000), CONST64(0x0400000400040000), CONST64(0x0400000000040004), CONST64(0x0400000400040004), + CONST64(0x0400040000040000), CONST64(0x0400040400040000), CONST64(0x0400040000040004), CONST64(0x0400040400040004), + CONST64(0x0400000000040400), CONST64(0x0400000400040400), CONST64(0x0400000000040404), CONST64(0x0400000400040404), + CONST64(0x0400040000040400), CONST64(0x0400040400040400), CONST64(0x0400040000040404), CONST64(0x0400040400040404), + CONST64(0x0404000000040000), CONST64(0x0404000400040000), CONST64(0x0404000000040004), CONST64(0x0404000400040004), + CONST64(0x0404040000040000), CONST64(0x0404040400040000), CONST64(0x0404040000040004), CONST64(0x0404040400040004), + CONST64(0x0404000000040400), CONST64(0x0404000400040400), CONST64(0x0404000000040404), CONST64(0x0404000400040404), + CONST64(0x0404040000040400), CONST64(0x0404040400040400), CONST64(0x0404040000040404), CONST64(0x0404040400040404), + CONST64(0x0000000004000000), CONST64(0x0000000404000000), CONST64(0x0000000004000004), CONST64(0x0000000404000004), + CONST64(0x0000040004000000), CONST64(0x0000040404000000), CONST64(0x0000040004000004), CONST64(0x0000040404000004), + CONST64(0x0000000004000400), CONST64(0x0000000404000400), CONST64(0x0000000004000404), CONST64(0x0000000404000404), + CONST64(0x0000040004000400), CONST64(0x0000040404000400), CONST64(0x0000040004000404), CONST64(0x0000040404000404), + CONST64(0x0004000004000000), CONST64(0x0004000404000000), CONST64(0x0004000004000004), CONST64(0x0004000404000004), + CONST64(0x0004040004000000), CONST64(0x0004040404000000), CONST64(0x0004040004000004), CONST64(0x0004040404000004), + CONST64(0x0004000004000400), CONST64(0x0004000404000400), CONST64(0x0004000004000404), CONST64(0x0004000404000404), + CONST64(0x0004040004000400), CONST64(0x0004040404000400), CONST64(0x0004040004000404), CONST64(0x0004040404000404), + CONST64(0x0000000004040000), CONST64(0x0000000404040000), CONST64(0x0000000004040004), CONST64(0x0000000404040004), + CONST64(0x0000040004040000), CONST64(0x0000040404040000), CONST64(0x0000040004040004), CONST64(0x0000040404040004), + CONST64(0x0000000004040400), CONST64(0x0000000404040400), CONST64(0x0000000004040404), CONST64(0x0000000404040404), + CONST64(0x0000040004040400), CONST64(0x0000040404040400), CONST64(0x0000040004040404), CONST64(0x0000040404040404), + CONST64(0x0004000004040000), CONST64(0x0004000404040000), CONST64(0x0004000004040004), CONST64(0x0004000404040004), + CONST64(0x0004040004040000), CONST64(0x0004040404040000), CONST64(0x0004040004040004), CONST64(0x0004040404040004), + CONST64(0x0004000004040400), CONST64(0x0004000404040400), CONST64(0x0004000004040404), CONST64(0x0004000404040404), + CONST64(0x0004040004040400), CONST64(0x0004040404040400), CONST64(0x0004040004040404), CONST64(0x0004040404040404), + CONST64(0x0400000004000000), CONST64(0x0400000404000000), CONST64(0x0400000004000004), CONST64(0x0400000404000004), + CONST64(0x0400040004000000), CONST64(0x0400040404000000), CONST64(0x0400040004000004), CONST64(0x0400040404000004), + CONST64(0x0400000004000400), CONST64(0x0400000404000400), CONST64(0x0400000004000404), CONST64(0x0400000404000404), + CONST64(0x0400040004000400), CONST64(0x0400040404000400), CONST64(0x0400040004000404), CONST64(0x0400040404000404), + CONST64(0x0404000004000000), CONST64(0x0404000404000000), CONST64(0x0404000004000004), CONST64(0x0404000404000004), + CONST64(0x0404040004000000), CONST64(0x0404040404000000), CONST64(0x0404040004000004), CONST64(0x0404040404000004), + CONST64(0x0404000004000400), CONST64(0x0404000404000400), CONST64(0x0404000004000404), CONST64(0x0404000404000404), + CONST64(0x0404040004000400), CONST64(0x0404040404000400), CONST64(0x0404040004000404), CONST64(0x0404040404000404), + CONST64(0x0400000004040000), CONST64(0x0400000404040000), CONST64(0x0400000004040004), CONST64(0x0400000404040004), + CONST64(0x0400040004040000), CONST64(0x0400040404040000), CONST64(0x0400040004040004), CONST64(0x0400040404040004), + CONST64(0x0400000004040400), CONST64(0x0400000404040400), CONST64(0x0400000004040404), CONST64(0x0400000404040404), + CONST64(0x0400040004040400), CONST64(0x0400040404040400), CONST64(0x0400040004040404), CONST64(0x0400040404040404), + CONST64(0x0404000004040000), CONST64(0x0404000404040000), CONST64(0x0404000004040004), CONST64(0x0404000404040004), + CONST64(0x0404040004040000), CONST64(0x0404040404040000), CONST64(0x0404040004040004), CONST64(0x0404040404040004), + CONST64(0x0404000004040400), CONST64(0x0404000404040400), CONST64(0x0404000004040404), CONST64(0x0404000404040404), + CONST64(0x0404040004040400), CONST64(0x0404040404040400), CONST64(0x0404040004040404), CONST64(0x0404040404040404) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000000200000000), CONST64(0x0000000000000002), CONST64(0x0000000200000002), + CONST64(0x0000020000000000), CONST64(0x0000020200000000), CONST64(0x0000020000000002), CONST64(0x0000020200000002), + CONST64(0x0000000000000200), CONST64(0x0000000200000200), CONST64(0x0000000000000202), CONST64(0x0000000200000202), + CONST64(0x0000020000000200), CONST64(0x0000020200000200), CONST64(0x0000020000000202), CONST64(0x0000020200000202), + CONST64(0x0002000000000000), CONST64(0x0002000200000000), CONST64(0x0002000000000002), CONST64(0x0002000200000002), + CONST64(0x0002020000000000), CONST64(0x0002020200000000), CONST64(0x0002020000000002), CONST64(0x0002020200000002), + CONST64(0x0002000000000200), CONST64(0x0002000200000200), CONST64(0x0002000000000202), CONST64(0x0002000200000202), + CONST64(0x0002020000000200), CONST64(0x0002020200000200), CONST64(0x0002020000000202), CONST64(0x0002020200000202), + CONST64(0x0000000000020000), CONST64(0x0000000200020000), CONST64(0x0000000000020002), CONST64(0x0000000200020002), + CONST64(0x0000020000020000), CONST64(0x0000020200020000), CONST64(0x0000020000020002), CONST64(0x0000020200020002), + CONST64(0x0000000000020200), CONST64(0x0000000200020200), CONST64(0x0000000000020202), CONST64(0x0000000200020202), + CONST64(0x0000020000020200), CONST64(0x0000020200020200), CONST64(0x0000020000020202), CONST64(0x0000020200020202), + CONST64(0x0002000000020000), CONST64(0x0002000200020000), CONST64(0x0002000000020002), CONST64(0x0002000200020002), + CONST64(0x0002020000020000), CONST64(0x0002020200020000), CONST64(0x0002020000020002), CONST64(0x0002020200020002), + CONST64(0x0002000000020200), CONST64(0x0002000200020200), CONST64(0x0002000000020202), CONST64(0x0002000200020202), + CONST64(0x0002020000020200), CONST64(0x0002020200020200), CONST64(0x0002020000020202), CONST64(0x0002020200020202), + CONST64(0x0200000000000000), CONST64(0x0200000200000000), CONST64(0x0200000000000002), CONST64(0x0200000200000002), + CONST64(0x0200020000000000), CONST64(0x0200020200000000), CONST64(0x0200020000000002), CONST64(0x0200020200000002), + CONST64(0x0200000000000200), CONST64(0x0200000200000200), CONST64(0x0200000000000202), CONST64(0x0200000200000202), + CONST64(0x0200020000000200), CONST64(0x0200020200000200), CONST64(0x0200020000000202), CONST64(0x0200020200000202), + CONST64(0x0202000000000000), CONST64(0x0202000200000000), CONST64(0x0202000000000002), CONST64(0x0202000200000002), + CONST64(0x0202020000000000), CONST64(0x0202020200000000), CONST64(0x0202020000000002), CONST64(0x0202020200000002), + CONST64(0x0202000000000200), CONST64(0x0202000200000200), CONST64(0x0202000000000202), CONST64(0x0202000200000202), + CONST64(0x0202020000000200), CONST64(0x0202020200000200), CONST64(0x0202020000000202), CONST64(0x0202020200000202), + CONST64(0x0200000000020000), CONST64(0x0200000200020000), CONST64(0x0200000000020002), CONST64(0x0200000200020002), + CONST64(0x0200020000020000), CONST64(0x0200020200020000), CONST64(0x0200020000020002), CONST64(0x0200020200020002), + CONST64(0x0200000000020200), CONST64(0x0200000200020200), CONST64(0x0200000000020202), CONST64(0x0200000200020202), + CONST64(0x0200020000020200), CONST64(0x0200020200020200), CONST64(0x0200020000020202), CONST64(0x0200020200020202), + CONST64(0x0202000000020000), CONST64(0x0202000200020000), CONST64(0x0202000000020002), CONST64(0x0202000200020002), + CONST64(0x0202020000020000), CONST64(0x0202020200020000), CONST64(0x0202020000020002), CONST64(0x0202020200020002), + CONST64(0x0202000000020200), CONST64(0x0202000200020200), CONST64(0x0202000000020202), CONST64(0x0202000200020202), + CONST64(0x0202020000020200), CONST64(0x0202020200020200), CONST64(0x0202020000020202), CONST64(0x0202020200020202), + CONST64(0x0000000002000000), CONST64(0x0000000202000000), CONST64(0x0000000002000002), CONST64(0x0000000202000002), + CONST64(0x0000020002000000), CONST64(0x0000020202000000), CONST64(0x0000020002000002), CONST64(0x0000020202000002), + CONST64(0x0000000002000200), CONST64(0x0000000202000200), CONST64(0x0000000002000202), CONST64(0x0000000202000202), + CONST64(0x0000020002000200), CONST64(0x0000020202000200), CONST64(0x0000020002000202), CONST64(0x0000020202000202), + CONST64(0x0002000002000000), CONST64(0x0002000202000000), CONST64(0x0002000002000002), CONST64(0x0002000202000002), + CONST64(0x0002020002000000), CONST64(0x0002020202000000), CONST64(0x0002020002000002), CONST64(0x0002020202000002), + CONST64(0x0002000002000200), CONST64(0x0002000202000200), CONST64(0x0002000002000202), CONST64(0x0002000202000202), + CONST64(0x0002020002000200), CONST64(0x0002020202000200), CONST64(0x0002020002000202), CONST64(0x0002020202000202), + CONST64(0x0000000002020000), CONST64(0x0000000202020000), CONST64(0x0000000002020002), CONST64(0x0000000202020002), + CONST64(0x0000020002020000), CONST64(0x0000020202020000), CONST64(0x0000020002020002), CONST64(0x0000020202020002), + CONST64(0x0000000002020200), CONST64(0x0000000202020200), CONST64(0x0000000002020202), CONST64(0x0000000202020202), + CONST64(0x0000020002020200), CONST64(0x0000020202020200), CONST64(0x0000020002020202), CONST64(0x0000020202020202), + CONST64(0x0002000002020000), CONST64(0x0002000202020000), CONST64(0x0002000002020002), CONST64(0x0002000202020002), + CONST64(0x0002020002020000), CONST64(0x0002020202020000), CONST64(0x0002020002020002), CONST64(0x0002020202020002), + CONST64(0x0002000002020200), CONST64(0x0002000202020200), CONST64(0x0002000002020202), CONST64(0x0002000202020202), + CONST64(0x0002020002020200), CONST64(0x0002020202020200), CONST64(0x0002020002020202), CONST64(0x0002020202020202), + CONST64(0x0200000002000000), CONST64(0x0200000202000000), CONST64(0x0200000002000002), CONST64(0x0200000202000002), + CONST64(0x0200020002000000), CONST64(0x0200020202000000), CONST64(0x0200020002000002), CONST64(0x0200020202000002), + CONST64(0x0200000002000200), CONST64(0x0200000202000200), CONST64(0x0200000002000202), CONST64(0x0200000202000202), + CONST64(0x0200020002000200), CONST64(0x0200020202000200), CONST64(0x0200020002000202), CONST64(0x0200020202000202), + CONST64(0x0202000002000000), CONST64(0x0202000202000000), CONST64(0x0202000002000002), CONST64(0x0202000202000002), + CONST64(0x0202020002000000), CONST64(0x0202020202000000), CONST64(0x0202020002000002), CONST64(0x0202020202000002), + CONST64(0x0202000002000200), CONST64(0x0202000202000200), CONST64(0x0202000002000202), CONST64(0x0202000202000202), + CONST64(0x0202020002000200), CONST64(0x0202020202000200), CONST64(0x0202020002000202), CONST64(0x0202020202000202), + CONST64(0x0200000002020000), CONST64(0x0200000202020000), CONST64(0x0200000002020002), CONST64(0x0200000202020002), + CONST64(0x0200020002020000), CONST64(0x0200020202020000), CONST64(0x0200020002020002), CONST64(0x0200020202020002), + CONST64(0x0200000002020200), CONST64(0x0200000202020200), CONST64(0x0200000002020202), CONST64(0x0200000202020202), + CONST64(0x0200020002020200), CONST64(0x0200020202020200), CONST64(0x0200020002020202), CONST64(0x0200020202020202), + CONST64(0x0202000002020000), CONST64(0x0202000202020000), CONST64(0x0202000002020002), CONST64(0x0202000202020002), + CONST64(0x0202020002020000), CONST64(0x0202020202020000), CONST64(0x0202020002020002), CONST64(0x0202020202020002), + CONST64(0x0202000002020200), CONST64(0x0202000202020200), CONST64(0x0202000002020202), CONST64(0x0202000202020202), + CONST64(0x0202020002020200), CONST64(0x0202020202020200), CONST64(0x0202020002020202), CONST64(0x0202020202020202) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000010000000000), CONST64(0x0000000000000100), CONST64(0x0000010000000100), + CONST64(0x0001000000000000), CONST64(0x0001010000000000), CONST64(0x0001000000000100), CONST64(0x0001010000000100), + CONST64(0x0000000000010000), CONST64(0x0000010000010000), CONST64(0x0000000000010100), CONST64(0x0000010000010100), + CONST64(0x0001000000010000), CONST64(0x0001010000010000), CONST64(0x0001000000010100), CONST64(0x0001010000010100), + CONST64(0x0100000000000000), CONST64(0x0100010000000000), CONST64(0x0100000000000100), CONST64(0x0100010000000100), + CONST64(0x0101000000000000), CONST64(0x0101010000000000), CONST64(0x0101000000000100), CONST64(0x0101010000000100), + CONST64(0x0100000000010000), CONST64(0x0100010000010000), CONST64(0x0100000000010100), CONST64(0x0100010000010100), + CONST64(0x0101000000010000), CONST64(0x0101010000010000), CONST64(0x0101000000010100), CONST64(0x0101010000010100), + CONST64(0x0000000001000000), CONST64(0x0000010001000000), CONST64(0x0000000001000100), CONST64(0x0000010001000100), + CONST64(0x0001000001000000), CONST64(0x0001010001000000), CONST64(0x0001000001000100), CONST64(0x0001010001000100), + CONST64(0x0000000001010000), CONST64(0x0000010001010000), CONST64(0x0000000001010100), CONST64(0x0000010001010100), + CONST64(0x0001000001010000), CONST64(0x0001010001010000), CONST64(0x0001000001010100), CONST64(0x0001010001010100), + CONST64(0x0100000001000000), CONST64(0x0100010001000000), CONST64(0x0100000001000100), CONST64(0x0100010001000100), + CONST64(0x0101000001000000), CONST64(0x0101010001000000), CONST64(0x0101000001000100), CONST64(0x0101010001000100), + CONST64(0x0100000001010000), CONST64(0x0100010001010000), CONST64(0x0100000001010100), CONST64(0x0100010001010100), + CONST64(0x0101000001010000), CONST64(0x0101010001010000), CONST64(0x0101000001010100), CONST64(0x0101010001010100), + CONST64(0x0000000100000000), CONST64(0x0000010100000000), CONST64(0x0000000100000100), CONST64(0x0000010100000100), + CONST64(0x0001000100000000), CONST64(0x0001010100000000), CONST64(0x0001000100000100), CONST64(0x0001010100000100), + CONST64(0x0000000100010000), CONST64(0x0000010100010000), CONST64(0x0000000100010100), CONST64(0x0000010100010100), + CONST64(0x0001000100010000), CONST64(0x0001010100010000), CONST64(0x0001000100010100), CONST64(0x0001010100010100), + CONST64(0x0100000100000000), CONST64(0x0100010100000000), CONST64(0x0100000100000100), CONST64(0x0100010100000100), + CONST64(0x0101000100000000), CONST64(0x0101010100000000), CONST64(0x0101000100000100), CONST64(0x0101010100000100), + CONST64(0x0100000100010000), CONST64(0x0100010100010000), CONST64(0x0100000100010100), CONST64(0x0100010100010100), + CONST64(0x0101000100010000), CONST64(0x0101010100010000), CONST64(0x0101000100010100), CONST64(0x0101010100010100), + CONST64(0x0000000101000000), CONST64(0x0000010101000000), CONST64(0x0000000101000100), CONST64(0x0000010101000100), + CONST64(0x0001000101000000), CONST64(0x0001010101000000), CONST64(0x0001000101000100), CONST64(0x0001010101000100), + CONST64(0x0000000101010000), CONST64(0x0000010101010000), CONST64(0x0000000101010100), CONST64(0x0000010101010100), + CONST64(0x0001000101010000), CONST64(0x0001010101010000), CONST64(0x0001000101010100), CONST64(0x0001010101010100), + CONST64(0x0100000101000000), CONST64(0x0100010101000000), CONST64(0x0100000101000100), CONST64(0x0100010101000100), + CONST64(0x0101000101000000), CONST64(0x0101010101000000), CONST64(0x0101000101000100), CONST64(0x0101010101000100), + CONST64(0x0100000101010000), CONST64(0x0100010101010000), CONST64(0x0100000101010100), CONST64(0x0100010101010100), + CONST64(0x0101000101010000), CONST64(0x0101010101010000), CONST64(0x0101000101010100), CONST64(0x0101010101010100), + CONST64(0x0000000000000001), CONST64(0x0000010000000001), CONST64(0x0000000000000101), CONST64(0x0000010000000101), + CONST64(0x0001000000000001), CONST64(0x0001010000000001), CONST64(0x0001000000000101), CONST64(0x0001010000000101), + CONST64(0x0000000000010001), CONST64(0x0000010000010001), CONST64(0x0000000000010101), CONST64(0x0000010000010101), + CONST64(0x0001000000010001), CONST64(0x0001010000010001), CONST64(0x0001000000010101), CONST64(0x0001010000010101), + CONST64(0x0100000000000001), CONST64(0x0100010000000001), CONST64(0x0100000000000101), CONST64(0x0100010000000101), + CONST64(0x0101000000000001), CONST64(0x0101010000000001), CONST64(0x0101000000000101), CONST64(0x0101010000000101), + CONST64(0x0100000000010001), CONST64(0x0100010000010001), CONST64(0x0100000000010101), CONST64(0x0100010000010101), + CONST64(0x0101000000010001), CONST64(0x0101010000010001), CONST64(0x0101000000010101), CONST64(0x0101010000010101), + CONST64(0x0000000001000001), CONST64(0x0000010001000001), CONST64(0x0000000001000101), CONST64(0x0000010001000101), + CONST64(0x0001000001000001), CONST64(0x0001010001000001), CONST64(0x0001000001000101), CONST64(0x0001010001000101), + CONST64(0x0000000001010001), CONST64(0x0000010001010001), CONST64(0x0000000001010101), CONST64(0x0000010001010101), + CONST64(0x0001000001010001), CONST64(0x0001010001010001), CONST64(0x0001000001010101), CONST64(0x0001010001010101), + CONST64(0x0100000001000001), CONST64(0x0100010001000001), CONST64(0x0100000001000101), CONST64(0x0100010001000101), + CONST64(0x0101000001000001), CONST64(0x0101010001000001), CONST64(0x0101000001000101), CONST64(0x0101010001000101), + CONST64(0x0100000001010001), CONST64(0x0100010001010001), CONST64(0x0100000001010101), CONST64(0x0100010001010101), + CONST64(0x0101000001010001), CONST64(0x0101010001010001), CONST64(0x0101000001010101), CONST64(0x0101010001010101), + CONST64(0x0000000100000001), CONST64(0x0000010100000001), CONST64(0x0000000100000101), CONST64(0x0000010100000101), + CONST64(0x0001000100000001), CONST64(0x0001010100000001), CONST64(0x0001000100000101), CONST64(0x0001010100000101), + CONST64(0x0000000100010001), CONST64(0x0000010100010001), CONST64(0x0000000100010101), CONST64(0x0000010100010101), + CONST64(0x0001000100010001), CONST64(0x0001010100010001), CONST64(0x0001000100010101), CONST64(0x0001010100010101), + CONST64(0x0100000100000001), CONST64(0x0100010100000001), CONST64(0x0100000100000101), CONST64(0x0100010100000101), + CONST64(0x0101000100000001), CONST64(0x0101010100000001), CONST64(0x0101000100000101), CONST64(0x0101010100000101), + CONST64(0x0100000100010001), CONST64(0x0100010100010001), CONST64(0x0100000100010101), CONST64(0x0100010100010101), + CONST64(0x0101000100010001), CONST64(0x0101010100010001), CONST64(0x0101000100010101), CONST64(0x0101010100010101), + CONST64(0x0000000101000001), CONST64(0x0000010101000001), CONST64(0x0000000101000101), CONST64(0x0000010101000101), + CONST64(0x0001000101000001), CONST64(0x0001010101000001), CONST64(0x0001000101000101), CONST64(0x0001010101000101), + CONST64(0x0000000101010001), CONST64(0x0000010101010001), CONST64(0x0000000101010101), CONST64(0x0000010101010101), + CONST64(0x0001000101010001), CONST64(0x0001010101010001), CONST64(0x0001000101010101), CONST64(0x0001010101010101), + CONST64(0x0100000101000001), CONST64(0x0100010101000001), CONST64(0x0100000101000101), CONST64(0x0100010101000101), + CONST64(0x0101000101000001), CONST64(0x0101010101000001), CONST64(0x0101000101000101), CONST64(0x0101010101000101), + CONST64(0x0100000101010001), CONST64(0x0100010101010001), CONST64(0x0100000101010101), CONST64(0x0100010101010101), + CONST64(0x0101000101010001), CONST64(0x0101010101010001), CONST64(0x0101000101010101), CONST64(0x0101010101010101) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000008000000000), CONST64(0x0000000000000080), CONST64(0x0000008000000080), + CONST64(0x0000800000000000), CONST64(0x0000808000000000), CONST64(0x0000800000000080), CONST64(0x0000808000000080), + CONST64(0x0000000000008000), CONST64(0x0000008000008000), CONST64(0x0000000000008080), CONST64(0x0000008000008080), + CONST64(0x0000800000008000), CONST64(0x0000808000008000), CONST64(0x0000800000008080), CONST64(0x0000808000008080), + CONST64(0x0080000000000000), CONST64(0x0080008000000000), CONST64(0x0080000000000080), CONST64(0x0080008000000080), + CONST64(0x0080800000000000), CONST64(0x0080808000000000), CONST64(0x0080800000000080), CONST64(0x0080808000000080), + CONST64(0x0080000000008000), CONST64(0x0080008000008000), CONST64(0x0080000000008080), CONST64(0x0080008000008080), + CONST64(0x0080800000008000), CONST64(0x0080808000008000), CONST64(0x0080800000008080), CONST64(0x0080808000008080), + CONST64(0x0000000000800000), CONST64(0x0000008000800000), CONST64(0x0000000000800080), CONST64(0x0000008000800080), + CONST64(0x0000800000800000), CONST64(0x0000808000800000), CONST64(0x0000800000800080), CONST64(0x0000808000800080), + CONST64(0x0000000000808000), CONST64(0x0000008000808000), CONST64(0x0000000000808080), CONST64(0x0000008000808080), + CONST64(0x0000800000808000), CONST64(0x0000808000808000), CONST64(0x0000800000808080), CONST64(0x0000808000808080), + CONST64(0x0080000000800000), CONST64(0x0080008000800000), CONST64(0x0080000000800080), CONST64(0x0080008000800080), + CONST64(0x0080800000800000), CONST64(0x0080808000800000), CONST64(0x0080800000800080), CONST64(0x0080808000800080), + CONST64(0x0080000000808000), CONST64(0x0080008000808000), CONST64(0x0080000000808080), CONST64(0x0080008000808080), + CONST64(0x0080800000808000), CONST64(0x0080808000808000), CONST64(0x0080800000808080), CONST64(0x0080808000808080), + CONST64(0x8000000000000000), CONST64(0x8000008000000000), CONST64(0x8000000000000080), CONST64(0x8000008000000080), + CONST64(0x8000800000000000), CONST64(0x8000808000000000), CONST64(0x8000800000000080), CONST64(0x8000808000000080), + CONST64(0x8000000000008000), CONST64(0x8000008000008000), CONST64(0x8000000000008080), CONST64(0x8000008000008080), + CONST64(0x8000800000008000), CONST64(0x8000808000008000), CONST64(0x8000800000008080), CONST64(0x8000808000008080), + CONST64(0x8080000000000000), CONST64(0x8080008000000000), CONST64(0x8080000000000080), CONST64(0x8080008000000080), + CONST64(0x8080800000000000), CONST64(0x8080808000000000), CONST64(0x8080800000000080), CONST64(0x8080808000000080), + CONST64(0x8080000000008000), CONST64(0x8080008000008000), CONST64(0x8080000000008080), CONST64(0x8080008000008080), + CONST64(0x8080800000008000), CONST64(0x8080808000008000), CONST64(0x8080800000008080), CONST64(0x8080808000008080), + CONST64(0x8000000000800000), CONST64(0x8000008000800000), CONST64(0x8000000000800080), CONST64(0x8000008000800080), + CONST64(0x8000800000800000), CONST64(0x8000808000800000), CONST64(0x8000800000800080), CONST64(0x8000808000800080), + CONST64(0x8000000000808000), CONST64(0x8000008000808000), CONST64(0x8000000000808080), CONST64(0x8000008000808080), + CONST64(0x8000800000808000), CONST64(0x8000808000808000), CONST64(0x8000800000808080), CONST64(0x8000808000808080), + CONST64(0x8080000000800000), CONST64(0x8080008000800000), CONST64(0x8080000000800080), CONST64(0x8080008000800080), + CONST64(0x8080800000800000), CONST64(0x8080808000800000), CONST64(0x8080800000800080), CONST64(0x8080808000800080), + CONST64(0x8080000000808000), CONST64(0x8080008000808000), CONST64(0x8080000000808080), CONST64(0x8080008000808080), + CONST64(0x8080800000808000), CONST64(0x8080808000808000), CONST64(0x8080800000808080), CONST64(0x8080808000808080), + CONST64(0x0000000080000000), CONST64(0x0000008080000000), CONST64(0x0000000080000080), CONST64(0x0000008080000080), + CONST64(0x0000800080000000), CONST64(0x0000808080000000), CONST64(0x0000800080000080), CONST64(0x0000808080000080), + CONST64(0x0000000080008000), CONST64(0x0000008080008000), CONST64(0x0000000080008080), CONST64(0x0000008080008080), + CONST64(0x0000800080008000), CONST64(0x0000808080008000), CONST64(0x0000800080008080), CONST64(0x0000808080008080), + CONST64(0x0080000080000000), CONST64(0x0080008080000000), CONST64(0x0080000080000080), CONST64(0x0080008080000080), + CONST64(0x0080800080000000), CONST64(0x0080808080000000), CONST64(0x0080800080000080), CONST64(0x0080808080000080), + CONST64(0x0080000080008000), CONST64(0x0080008080008000), CONST64(0x0080000080008080), CONST64(0x0080008080008080), + CONST64(0x0080800080008000), CONST64(0x0080808080008000), CONST64(0x0080800080008080), CONST64(0x0080808080008080), + CONST64(0x0000000080800000), CONST64(0x0000008080800000), CONST64(0x0000000080800080), CONST64(0x0000008080800080), + CONST64(0x0000800080800000), CONST64(0x0000808080800000), CONST64(0x0000800080800080), CONST64(0x0000808080800080), + CONST64(0x0000000080808000), CONST64(0x0000008080808000), CONST64(0x0000000080808080), CONST64(0x0000008080808080), + CONST64(0x0000800080808000), CONST64(0x0000808080808000), CONST64(0x0000800080808080), CONST64(0x0000808080808080), + CONST64(0x0080000080800000), CONST64(0x0080008080800000), CONST64(0x0080000080800080), CONST64(0x0080008080800080), + CONST64(0x0080800080800000), CONST64(0x0080808080800000), CONST64(0x0080800080800080), CONST64(0x0080808080800080), + CONST64(0x0080000080808000), CONST64(0x0080008080808000), CONST64(0x0080000080808080), CONST64(0x0080008080808080), + CONST64(0x0080800080808000), CONST64(0x0080808080808000), CONST64(0x0080800080808080), CONST64(0x0080808080808080), + CONST64(0x8000000080000000), CONST64(0x8000008080000000), CONST64(0x8000000080000080), CONST64(0x8000008080000080), + CONST64(0x8000800080000000), CONST64(0x8000808080000000), CONST64(0x8000800080000080), CONST64(0x8000808080000080), + CONST64(0x8000000080008000), CONST64(0x8000008080008000), CONST64(0x8000000080008080), CONST64(0x8000008080008080), + CONST64(0x8000800080008000), CONST64(0x8000808080008000), CONST64(0x8000800080008080), CONST64(0x8000808080008080), + CONST64(0x8080000080000000), CONST64(0x8080008080000000), CONST64(0x8080000080000080), CONST64(0x8080008080000080), + CONST64(0x8080800080000000), CONST64(0x8080808080000000), CONST64(0x8080800080000080), CONST64(0x8080808080000080), + CONST64(0x8080000080008000), CONST64(0x8080008080008000), CONST64(0x8080000080008080), CONST64(0x8080008080008080), + CONST64(0x8080800080008000), CONST64(0x8080808080008000), CONST64(0x8080800080008080), CONST64(0x8080808080008080), + CONST64(0x8000000080800000), CONST64(0x8000008080800000), CONST64(0x8000000080800080), CONST64(0x8000008080800080), + CONST64(0x8000800080800000), CONST64(0x8000808080800000), CONST64(0x8000800080800080), CONST64(0x8000808080800080), + CONST64(0x8000000080808000), CONST64(0x8000008080808000), CONST64(0x8000000080808080), CONST64(0x8000008080808080), + CONST64(0x8000800080808000), CONST64(0x8000808080808000), CONST64(0x8000800080808080), CONST64(0x8000808080808080), + CONST64(0x8080000080800000), CONST64(0x8080008080800000), CONST64(0x8080000080800080), CONST64(0x8080008080800080), + CONST64(0x8080800080800000), CONST64(0x8080808080800000), CONST64(0x8080800080800080), CONST64(0x8080808080800080), + CONST64(0x8080000080808000), CONST64(0x8080008080808000), CONST64(0x8080000080808080), CONST64(0x8080008080808080), + CONST64(0x8080800080808000), CONST64(0x8080808080808000), CONST64(0x8080800080808080), CONST64(0x8080808080808080) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000004000000000), CONST64(0x0000000000000040), CONST64(0x0000004000000040), + CONST64(0x0000400000000000), CONST64(0x0000404000000000), CONST64(0x0000400000000040), CONST64(0x0000404000000040), + CONST64(0x0000000000004000), CONST64(0x0000004000004000), CONST64(0x0000000000004040), CONST64(0x0000004000004040), + CONST64(0x0000400000004000), CONST64(0x0000404000004000), CONST64(0x0000400000004040), CONST64(0x0000404000004040), + CONST64(0x0040000000000000), CONST64(0x0040004000000000), CONST64(0x0040000000000040), CONST64(0x0040004000000040), + CONST64(0x0040400000000000), CONST64(0x0040404000000000), CONST64(0x0040400000000040), CONST64(0x0040404000000040), + CONST64(0x0040000000004000), CONST64(0x0040004000004000), CONST64(0x0040000000004040), CONST64(0x0040004000004040), + CONST64(0x0040400000004000), CONST64(0x0040404000004000), CONST64(0x0040400000004040), CONST64(0x0040404000004040), + CONST64(0x0000000000400000), CONST64(0x0000004000400000), CONST64(0x0000000000400040), CONST64(0x0000004000400040), + CONST64(0x0000400000400000), CONST64(0x0000404000400000), CONST64(0x0000400000400040), CONST64(0x0000404000400040), + CONST64(0x0000000000404000), CONST64(0x0000004000404000), CONST64(0x0000000000404040), CONST64(0x0000004000404040), + CONST64(0x0000400000404000), CONST64(0x0000404000404000), CONST64(0x0000400000404040), CONST64(0x0000404000404040), + CONST64(0x0040000000400000), CONST64(0x0040004000400000), CONST64(0x0040000000400040), CONST64(0x0040004000400040), + CONST64(0x0040400000400000), CONST64(0x0040404000400000), CONST64(0x0040400000400040), CONST64(0x0040404000400040), + CONST64(0x0040000000404000), CONST64(0x0040004000404000), CONST64(0x0040000000404040), CONST64(0x0040004000404040), + CONST64(0x0040400000404000), CONST64(0x0040404000404000), CONST64(0x0040400000404040), CONST64(0x0040404000404040), + CONST64(0x4000000000000000), CONST64(0x4000004000000000), CONST64(0x4000000000000040), CONST64(0x4000004000000040), + CONST64(0x4000400000000000), CONST64(0x4000404000000000), CONST64(0x4000400000000040), CONST64(0x4000404000000040), + CONST64(0x4000000000004000), CONST64(0x4000004000004000), CONST64(0x4000000000004040), CONST64(0x4000004000004040), + CONST64(0x4000400000004000), CONST64(0x4000404000004000), CONST64(0x4000400000004040), CONST64(0x4000404000004040), + CONST64(0x4040000000000000), CONST64(0x4040004000000000), CONST64(0x4040000000000040), CONST64(0x4040004000000040), + CONST64(0x4040400000000000), CONST64(0x4040404000000000), CONST64(0x4040400000000040), CONST64(0x4040404000000040), + CONST64(0x4040000000004000), CONST64(0x4040004000004000), CONST64(0x4040000000004040), CONST64(0x4040004000004040), + CONST64(0x4040400000004000), CONST64(0x4040404000004000), CONST64(0x4040400000004040), CONST64(0x4040404000004040), + CONST64(0x4000000000400000), CONST64(0x4000004000400000), CONST64(0x4000000000400040), CONST64(0x4000004000400040), + CONST64(0x4000400000400000), CONST64(0x4000404000400000), CONST64(0x4000400000400040), CONST64(0x4000404000400040), + CONST64(0x4000000000404000), CONST64(0x4000004000404000), CONST64(0x4000000000404040), CONST64(0x4000004000404040), + CONST64(0x4000400000404000), CONST64(0x4000404000404000), CONST64(0x4000400000404040), CONST64(0x4000404000404040), + CONST64(0x4040000000400000), CONST64(0x4040004000400000), CONST64(0x4040000000400040), CONST64(0x4040004000400040), + CONST64(0x4040400000400000), CONST64(0x4040404000400000), CONST64(0x4040400000400040), CONST64(0x4040404000400040), + CONST64(0x4040000000404000), CONST64(0x4040004000404000), CONST64(0x4040000000404040), CONST64(0x4040004000404040), + CONST64(0x4040400000404000), CONST64(0x4040404000404000), CONST64(0x4040400000404040), CONST64(0x4040404000404040), + CONST64(0x0000000040000000), CONST64(0x0000004040000000), CONST64(0x0000000040000040), CONST64(0x0000004040000040), + CONST64(0x0000400040000000), CONST64(0x0000404040000000), CONST64(0x0000400040000040), CONST64(0x0000404040000040), + CONST64(0x0000000040004000), CONST64(0x0000004040004000), CONST64(0x0000000040004040), CONST64(0x0000004040004040), + CONST64(0x0000400040004000), CONST64(0x0000404040004000), CONST64(0x0000400040004040), CONST64(0x0000404040004040), + CONST64(0x0040000040000000), CONST64(0x0040004040000000), CONST64(0x0040000040000040), CONST64(0x0040004040000040), + CONST64(0x0040400040000000), CONST64(0x0040404040000000), CONST64(0x0040400040000040), CONST64(0x0040404040000040), + CONST64(0x0040000040004000), CONST64(0x0040004040004000), CONST64(0x0040000040004040), CONST64(0x0040004040004040), + CONST64(0x0040400040004000), CONST64(0x0040404040004000), CONST64(0x0040400040004040), CONST64(0x0040404040004040), + CONST64(0x0000000040400000), CONST64(0x0000004040400000), CONST64(0x0000000040400040), CONST64(0x0000004040400040), + CONST64(0x0000400040400000), CONST64(0x0000404040400000), CONST64(0x0000400040400040), CONST64(0x0000404040400040), + CONST64(0x0000000040404000), CONST64(0x0000004040404000), CONST64(0x0000000040404040), CONST64(0x0000004040404040), + CONST64(0x0000400040404000), CONST64(0x0000404040404000), CONST64(0x0000400040404040), CONST64(0x0000404040404040), + CONST64(0x0040000040400000), CONST64(0x0040004040400000), CONST64(0x0040000040400040), CONST64(0x0040004040400040), + CONST64(0x0040400040400000), CONST64(0x0040404040400000), CONST64(0x0040400040400040), CONST64(0x0040404040400040), + CONST64(0x0040000040404000), CONST64(0x0040004040404000), CONST64(0x0040000040404040), CONST64(0x0040004040404040), + CONST64(0x0040400040404000), CONST64(0x0040404040404000), CONST64(0x0040400040404040), CONST64(0x0040404040404040), + CONST64(0x4000000040000000), CONST64(0x4000004040000000), CONST64(0x4000000040000040), CONST64(0x4000004040000040), + CONST64(0x4000400040000000), CONST64(0x4000404040000000), CONST64(0x4000400040000040), CONST64(0x4000404040000040), + CONST64(0x4000000040004000), CONST64(0x4000004040004000), CONST64(0x4000000040004040), CONST64(0x4000004040004040), + CONST64(0x4000400040004000), CONST64(0x4000404040004000), CONST64(0x4000400040004040), CONST64(0x4000404040004040), + CONST64(0x4040000040000000), CONST64(0x4040004040000000), CONST64(0x4040000040000040), CONST64(0x4040004040000040), + CONST64(0x4040400040000000), CONST64(0x4040404040000000), CONST64(0x4040400040000040), CONST64(0x4040404040000040), + CONST64(0x4040000040004000), CONST64(0x4040004040004000), CONST64(0x4040000040004040), CONST64(0x4040004040004040), + CONST64(0x4040400040004000), CONST64(0x4040404040004000), CONST64(0x4040400040004040), CONST64(0x4040404040004040), + CONST64(0x4000000040400000), CONST64(0x4000004040400000), CONST64(0x4000000040400040), CONST64(0x4000004040400040), + CONST64(0x4000400040400000), CONST64(0x4000404040400000), CONST64(0x4000400040400040), CONST64(0x4000404040400040), + CONST64(0x4000000040404000), CONST64(0x4000004040404000), CONST64(0x4000000040404040), CONST64(0x4000004040404040), + CONST64(0x4000400040404000), CONST64(0x4000404040404000), CONST64(0x4000400040404040), CONST64(0x4000404040404040), + CONST64(0x4040000040400000), CONST64(0x4040004040400000), CONST64(0x4040000040400040), CONST64(0x4040004040400040), + CONST64(0x4040400040400000), CONST64(0x4040404040400000), CONST64(0x4040400040400040), CONST64(0x4040404040400040), + CONST64(0x4040000040404000), CONST64(0x4040004040404000), CONST64(0x4040000040404040), CONST64(0x4040004040404040), + CONST64(0x4040400040404000), CONST64(0x4040404040404000), CONST64(0x4040400040404040), CONST64(0x4040404040404040) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000002000000000), CONST64(0x0000000000000020), CONST64(0x0000002000000020), + CONST64(0x0000200000000000), CONST64(0x0000202000000000), CONST64(0x0000200000000020), CONST64(0x0000202000000020), + CONST64(0x0000000000002000), CONST64(0x0000002000002000), CONST64(0x0000000000002020), CONST64(0x0000002000002020), + CONST64(0x0000200000002000), CONST64(0x0000202000002000), CONST64(0x0000200000002020), CONST64(0x0000202000002020), + CONST64(0x0020000000000000), CONST64(0x0020002000000000), CONST64(0x0020000000000020), CONST64(0x0020002000000020), + CONST64(0x0020200000000000), CONST64(0x0020202000000000), CONST64(0x0020200000000020), CONST64(0x0020202000000020), + CONST64(0x0020000000002000), CONST64(0x0020002000002000), CONST64(0x0020000000002020), CONST64(0x0020002000002020), + CONST64(0x0020200000002000), CONST64(0x0020202000002000), CONST64(0x0020200000002020), CONST64(0x0020202000002020), + CONST64(0x0000000000200000), CONST64(0x0000002000200000), CONST64(0x0000000000200020), CONST64(0x0000002000200020), + CONST64(0x0000200000200000), CONST64(0x0000202000200000), CONST64(0x0000200000200020), CONST64(0x0000202000200020), + CONST64(0x0000000000202000), CONST64(0x0000002000202000), CONST64(0x0000000000202020), CONST64(0x0000002000202020), + CONST64(0x0000200000202000), CONST64(0x0000202000202000), CONST64(0x0000200000202020), CONST64(0x0000202000202020), + CONST64(0x0020000000200000), CONST64(0x0020002000200000), CONST64(0x0020000000200020), CONST64(0x0020002000200020), + CONST64(0x0020200000200000), CONST64(0x0020202000200000), CONST64(0x0020200000200020), CONST64(0x0020202000200020), + CONST64(0x0020000000202000), CONST64(0x0020002000202000), CONST64(0x0020000000202020), CONST64(0x0020002000202020), + CONST64(0x0020200000202000), CONST64(0x0020202000202000), CONST64(0x0020200000202020), CONST64(0x0020202000202020), + CONST64(0x2000000000000000), CONST64(0x2000002000000000), CONST64(0x2000000000000020), CONST64(0x2000002000000020), + CONST64(0x2000200000000000), CONST64(0x2000202000000000), CONST64(0x2000200000000020), CONST64(0x2000202000000020), + CONST64(0x2000000000002000), CONST64(0x2000002000002000), CONST64(0x2000000000002020), CONST64(0x2000002000002020), + CONST64(0x2000200000002000), CONST64(0x2000202000002000), CONST64(0x2000200000002020), CONST64(0x2000202000002020), + CONST64(0x2020000000000000), CONST64(0x2020002000000000), CONST64(0x2020000000000020), CONST64(0x2020002000000020), + CONST64(0x2020200000000000), CONST64(0x2020202000000000), CONST64(0x2020200000000020), CONST64(0x2020202000000020), + CONST64(0x2020000000002000), CONST64(0x2020002000002000), CONST64(0x2020000000002020), CONST64(0x2020002000002020), + CONST64(0x2020200000002000), CONST64(0x2020202000002000), CONST64(0x2020200000002020), CONST64(0x2020202000002020), + CONST64(0x2000000000200000), CONST64(0x2000002000200000), CONST64(0x2000000000200020), CONST64(0x2000002000200020), + CONST64(0x2000200000200000), CONST64(0x2000202000200000), CONST64(0x2000200000200020), CONST64(0x2000202000200020), + CONST64(0x2000000000202000), CONST64(0x2000002000202000), CONST64(0x2000000000202020), CONST64(0x2000002000202020), + CONST64(0x2000200000202000), CONST64(0x2000202000202000), CONST64(0x2000200000202020), CONST64(0x2000202000202020), + CONST64(0x2020000000200000), CONST64(0x2020002000200000), CONST64(0x2020000000200020), CONST64(0x2020002000200020), + CONST64(0x2020200000200000), CONST64(0x2020202000200000), CONST64(0x2020200000200020), CONST64(0x2020202000200020), + CONST64(0x2020000000202000), CONST64(0x2020002000202000), CONST64(0x2020000000202020), CONST64(0x2020002000202020), + CONST64(0x2020200000202000), CONST64(0x2020202000202000), CONST64(0x2020200000202020), CONST64(0x2020202000202020), + CONST64(0x0000000020000000), CONST64(0x0000002020000000), CONST64(0x0000000020000020), CONST64(0x0000002020000020), + CONST64(0x0000200020000000), CONST64(0x0000202020000000), CONST64(0x0000200020000020), CONST64(0x0000202020000020), + CONST64(0x0000000020002000), CONST64(0x0000002020002000), CONST64(0x0000000020002020), CONST64(0x0000002020002020), + CONST64(0x0000200020002000), CONST64(0x0000202020002000), CONST64(0x0000200020002020), CONST64(0x0000202020002020), + CONST64(0x0020000020000000), CONST64(0x0020002020000000), CONST64(0x0020000020000020), CONST64(0x0020002020000020), + CONST64(0x0020200020000000), CONST64(0x0020202020000000), CONST64(0x0020200020000020), CONST64(0x0020202020000020), + CONST64(0x0020000020002000), CONST64(0x0020002020002000), CONST64(0x0020000020002020), CONST64(0x0020002020002020), + CONST64(0x0020200020002000), CONST64(0x0020202020002000), CONST64(0x0020200020002020), CONST64(0x0020202020002020), + CONST64(0x0000000020200000), CONST64(0x0000002020200000), CONST64(0x0000000020200020), CONST64(0x0000002020200020), + CONST64(0x0000200020200000), CONST64(0x0000202020200000), CONST64(0x0000200020200020), CONST64(0x0000202020200020), + CONST64(0x0000000020202000), CONST64(0x0000002020202000), CONST64(0x0000000020202020), CONST64(0x0000002020202020), + CONST64(0x0000200020202000), CONST64(0x0000202020202000), CONST64(0x0000200020202020), CONST64(0x0000202020202020), + CONST64(0x0020000020200000), CONST64(0x0020002020200000), CONST64(0x0020000020200020), CONST64(0x0020002020200020), + CONST64(0x0020200020200000), CONST64(0x0020202020200000), CONST64(0x0020200020200020), CONST64(0x0020202020200020), + CONST64(0x0020000020202000), CONST64(0x0020002020202000), CONST64(0x0020000020202020), CONST64(0x0020002020202020), + CONST64(0x0020200020202000), CONST64(0x0020202020202000), CONST64(0x0020200020202020), CONST64(0x0020202020202020), + CONST64(0x2000000020000000), CONST64(0x2000002020000000), CONST64(0x2000000020000020), CONST64(0x2000002020000020), + CONST64(0x2000200020000000), CONST64(0x2000202020000000), CONST64(0x2000200020000020), CONST64(0x2000202020000020), + CONST64(0x2000000020002000), CONST64(0x2000002020002000), CONST64(0x2000000020002020), CONST64(0x2000002020002020), + CONST64(0x2000200020002000), CONST64(0x2000202020002000), CONST64(0x2000200020002020), CONST64(0x2000202020002020), + CONST64(0x2020000020000000), CONST64(0x2020002020000000), CONST64(0x2020000020000020), CONST64(0x2020002020000020), + CONST64(0x2020200020000000), CONST64(0x2020202020000000), CONST64(0x2020200020000020), CONST64(0x2020202020000020), + CONST64(0x2020000020002000), CONST64(0x2020002020002000), CONST64(0x2020000020002020), CONST64(0x2020002020002020), + CONST64(0x2020200020002000), CONST64(0x2020202020002000), CONST64(0x2020200020002020), CONST64(0x2020202020002020), + CONST64(0x2000000020200000), CONST64(0x2000002020200000), CONST64(0x2000000020200020), CONST64(0x2000002020200020), + CONST64(0x2000200020200000), CONST64(0x2000202020200000), CONST64(0x2000200020200020), CONST64(0x2000202020200020), + CONST64(0x2000000020202000), CONST64(0x2000002020202000), CONST64(0x2000000020202020), CONST64(0x2000002020202020), + CONST64(0x2000200020202000), CONST64(0x2000202020202000), CONST64(0x2000200020202020), CONST64(0x2000202020202020), + CONST64(0x2020000020200000), CONST64(0x2020002020200000), CONST64(0x2020000020200020), CONST64(0x2020002020200020), + CONST64(0x2020200020200000), CONST64(0x2020202020200000), CONST64(0x2020200020200020), CONST64(0x2020202020200020), + CONST64(0x2020000020202000), CONST64(0x2020002020202000), CONST64(0x2020000020202020), CONST64(0x2020002020202020), + CONST64(0x2020200020202000), CONST64(0x2020202020202000), CONST64(0x2020200020202020), CONST64(0x2020202020202020) + }}; + +static const ulong64 des_fp[8][256] = { + +{ CONST64(0x0000000000000000), CONST64(0x0000008000000000), CONST64(0x0000000002000000), CONST64(0x0000008002000000), + CONST64(0x0000000000020000), CONST64(0x0000008000020000), CONST64(0x0000000002020000), CONST64(0x0000008002020000), + CONST64(0x0000000000000200), CONST64(0x0000008000000200), CONST64(0x0000000002000200), CONST64(0x0000008002000200), + CONST64(0x0000000000020200), CONST64(0x0000008000020200), CONST64(0x0000000002020200), CONST64(0x0000008002020200), + CONST64(0x0000000000000002), CONST64(0x0000008000000002), CONST64(0x0000000002000002), CONST64(0x0000008002000002), + CONST64(0x0000000000020002), CONST64(0x0000008000020002), CONST64(0x0000000002020002), CONST64(0x0000008002020002), + CONST64(0x0000000000000202), CONST64(0x0000008000000202), CONST64(0x0000000002000202), CONST64(0x0000008002000202), + CONST64(0x0000000000020202), CONST64(0x0000008000020202), CONST64(0x0000000002020202), CONST64(0x0000008002020202), + CONST64(0x0200000000000000), CONST64(0x0200008000000000), CONST64(0x0200000002000000), CONST64(0x0200008002000000), + CONST64(0x0200000000020000), CONST64(0x0200008000020000), CONST64(0x0200000002020000), CONST64(0x0200008002020000), + CONST64(0x0200000000000200), CONST64(0x0200008000000200), CONST64(0x0200000002000200), CONST64(0x0200008002000200), + CONST64(0x0200000000020200), CONST64(0x0200008000020200), CONST64(0x0200000002020200), CONST64(0x0200008002020200), + CONST64(0x0200000000000002), CONST64(0x0200008000000002), CONST64(0x0200000002000002), CONST64(0x0200008002000002), + CONST64(0x0200000000020002), CONST64(0x0200008000020002), CONST64(0x0200000002020002), CONST64(0x0200008002020002), + CONST64(0x0200000000000202), CONST64(0x0200008000000202), CONST64(0x0200000002000202), CONST64(0x0200008002000202), + CONST64(0x0200000000020202), CONST64(0x0200008000020202), CONST64(0x0200000002020202), CONST64(0x0200008002020202), + CONST64(0x0002000000000000), CONST64(0x0002008000000000), CONST64(0x0002000002000000), CONST64(0x0002008002000000), + CONST64(0x0002000000020000), CONST64(0x0002008000020000), CONST64(0x0002000002020000), CONST64(0x0002008002020000), + CONST64(0x0002000000000200), CONST64(0x0002008000000200), CONST64(0x0002000002000200), CONST64(0x0002008002000200), + CONST64(0x0002000000020200), CONST64(0x0002008000020200), CONST64(0x0002000002020200), CONST64(0x0002008002020200), + CONST64(0x0002000000000002), CONST64(0x0002008000000002), CONST64(0x0002000002000002), CONST64(0x0002008002000002), + CONST64(0x0002000000020002), CONST64(0x0002008000020002), CONST64(0x0002000002020002), CONST64(0x0002008002020002), + CONST64(0x0002000000000202), CONST64(0x0002008000000202), CONST64(0x0002000002000202), CONST64(0x0002008002000202), + CONST64(0x0002000000020202), CONST64(0x0002008000020202), CONST64(0x0002000002020202), CONST64(0x0002008002020202), + CONST64(0x0202000000000000), CONST64(0x0202008000000000), CONST64(0x0202000002000000), CONST64(0x0202008002000000), + CONST64(0x0202000000020000), CONST64(0x0202008000020000), CONST64(0x0202000002020000), CONST64(0x0202008002020000), + CONST64(0x0202000000000200), CONST64(0x0202008000000200), CONST64(0x0202000002000200), CONST64(0x0202008002000200), + CONST64(0x0202000000020200), CONST64(0x0202008000020200), CONST64(0x0202000002020200), CONST64(0x0202008002020200), + CONST64(0x0202000000000002), CONST64(0x0202008000000002), CONST64(0x0202000002000002), CONST64(0x0202008002000002), + CONST64(0x0202000000020002), CONST64(0x0202008000020002), CONST64(0x0202000002020002), CONST64(0x0202008002020002), + CONST64(0x0202000000000202), CONST64(0x0202008000000202), CONST64(0x0202000002000202), CONST64(0x0202008002000202), + CONST64(0x0202000000020202), CONST64(0x0202008000020202), CONST64(0x0202000002020202), CONST64(0x0202008002020202), + CONST64(0x0000020000000000), CONST64(0x0000028000000000), CONST64(0x0000020002000000), CONST64(0x0000028002000000), + CONST64(0x0000020000020000), CONST64(0x0000028000020000), CONST64(0x0000020002020000), CONST64(0x0000028002020000), + CONST64(0x0000020000000200), CONST64(0x0000028000000200), CONST64(0x0000020002000200), CONST64(0x0000028002000200), + CONST64(0x0000020000020200), CONST64(0x0000028000020200), CONST64(0x0000020002020200), CONST64(0x0000028002020200), + CONST64(0x0000020000000002), CONST64(0x0000028000000002), CONST64(0x0000020002000002), CONST64(0x0000028002000002), + CONST64(0x0000020000020002), CONST64(0x0000028000020002), CONST64(0x0000020002020002), CONST64(0x0000028002020002), + CONST64(0x0000020000000202), CONST64(0x0000028000000202), CONST64(0x0000020002000202), CONST64(0x0000028002000202), + CONST64(0x0000020000020202), CONST64(0x0000028000020202), CONST64(0x0000020002020202), CONST64(0x0000028002020202), + CONST64(0x0200020000000000), CONST64(0x0200028000000000), CONST64(0x0200020002000000), CONST64(0x0200028002000000), + CONST64(0x0200020000020000), CONST64(0x0200028000020000), CONST64(0x0200020002020000), CONST64(0x0200028002020000), + CONST64(0x0200020000000200), CONST64(0x0200028000000200), CONST64(0x0200020002000200), CONST64(0x0200028002000200), + CONST64(0x0200020000020200), CONST64(0x0200028000020200), CONST64(0x0200020002020200), CONST64(0x0200028002020200), + CONST64(0x0200020000000002), CONST64(0x0200028000000002), CONST64(0x0200020002000002), CONST64(0x0200028002000002), + CONST64(0x0200020000020002), CONST64(0x0200028000020002), CONST64(0x0200020002020002), CONST64(0x0200028002020002), + CONST64(0x0200020000000202), CONST64(0x0200028000000202), CONST64(0x0200020002000202), CONST64(0x0200028002000202), + CONST64(0x0200020000020202), CONST64(0x0200028000020202), CONST64(0x0200020002020202), CONST64(0x0200028002020202), + CONST64(0x0002020000000000), CONST64(0x0002028000000000), CONST64(0x0002020002000000), CONST64(0x0002028002000000), + CONST64(0x0002020000020000), CONST64(0x0002028000020000), CONST64(0x0002020002020000), CONST64(0x0002028002020000), + CONST64(0x0002020000000200), CONST64(0x0002028000000200), CONST64(0x0002020002000200), CONST64(0x0002028002000200), + CONST64(0x0002020000020200), CONST64(0x0002028000020200), CONST64(0x0002020002020200), CONST64(0x0002028002020200), + CONST64(0x0002020000000002), CONST64(0x0002028000000002), CONST64(0x0002020002000002), CONST64(0x0002028002000002), + CONST64(0x0002020000020002), CONST64(0x0002028000020002), CONST64(0x0002020002020002), CONST64(0x0002028002020002), + CONST64(0x0002020000000202), CONST64(0x0002028000000202), CONST64(0x0002020002000202), CONST64(0x0002028002000202), + CONST64(0x0002020000020202), CONST64(0x0002028000020202), CONST64(0x0002020002020202), CONST64(0x0002028002020202), + CONST64(0x0202020000000000), CONST64(0x0202028000000000), CONST64(0x0202020002000000), CONST64(0x0202028002000000), + CONST64(0x0202020000020000), CONST64(0x0202028000020000), CONST64(0x0202020002020000), CONST64(0x0202028002020000), + CONST64(0x0202020000000200), CONST64(0x0202028000000200), CONST64(0x0202020002000200), CONST64(0x0202028002000200), + CONST64(0x0202020000020200), CONST64(0x0202028000020200), CONST64(0x0202020002020200), CONST64(0x0202028002020200), + CONST64(0x0202020000000002), CONST64(0x0202028000000002), CONST64(0x0202020002000002), CONST64(0x0202028002000002), + CONST64(0x0202020000020002), CONST64(0x0202028000020002), CONST64(0x0202020002020002), CONST64(0x0202028002020002), + CONST64(0x0202020000000202), CONST64(0x0202028000000202), CONST64(0x0202020002000202), CONST64(0x0202028002000202), + CONST64(0x0202020000020202), CONST64(0x0202028000020202), CONST64(0x0202020002020202), CONST64(0x0202028002020202) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000000200000000), CONST64(0x0000000008000000), CONST64(0x0000000208000000), + CONST64(0x0000000000080000), CONST64(0x0000000200080000), CONST64(0x0000000008080000), CONST64(0x0000000208080000), + CONST64(0x0000000000000800), CONST64(0x0000000200000800), CONST64(0x0000000008000800), CONST64(0x0000000208000800), + CONST64(0x0000000000080800), CONST64(0x0000000200080800), CONST64(0x0000000008080800), CONST64(0x0000000208080800), + CONST64(0x0000000000000008), CONST64(0x0000000200000008), CONST64(0x0000000008000008), CONST64(0x0000000208000008), + CONST64(0x0000000000080008), CONST64(0x0000000200080008), CONST64(0x0000000008080008), CONST64(0x0000000208080008), + CONST64(0x0000000000000808), CONST64(0x0000000200000808), CONST64(0x0000000008000808), CONST64(0x0000000208000808), + CONST64(0x0000000000080808), CONST64(0x0000000200080808), CONST64(0x0000000008080808), CONST64(0x0000000208080808), + CONST64(0x0800000000000000), CONST64(0x0800000200000000), CONST64(0x0800000008000000), CONST64(0x0800000208000000), + CONST64(0x0800000000080000), CONST64(0x0800000200080000), CONST64(0x0800000008080000), CONST64(0x0800000208080000), + CONST64(0x0800000000000800), CONST64(0x0800000200000800), CONST64(0x0800000008000800), CONST64(0x0800000208000800), + CONST64(0x0800000000080800), CONST64(0x0800000200080800), CONST64(0x0800000008080800), CONST64(0x0800000208080800), + CONST64(0x0800000000000008), CONST64(0x0800000200000008), CONST64(0x0800000008000008), CONST64(0x0800000208000008), + CONST64(0x0800000000080008), CONST64(0x0800000200080008), CONST64(0x0800000008080008), CONST64(0x0800000208080008), + CONST64(0x0800000000000808), CONST64(0x0800000200000808), CONST64(0x0800000008000808), CONST64(0x0800000208000808), + CONST64(0x0800000000080808), CONST64(0x0800000200080808), CONST64(0x0800000008080808), CONST64(0x0800000208080808), + CONST64(0x0008000000000000), CONST64(0x0008000200000000), CONST64(0x0008000008000000), CONST64(0x0008000208000000), + CONST64(0x0008000000080000), CONST64(0x0008000200080000), CONST64(0x0008000008080000), CONST64(0x0008000208080000), + CONST64(0x0008000000000800), CONST64(0x0008000200000800), CONST64(0x0008000008000800), CONST64(0x0008000208000800), + CONST64(0x0008000000080800), CONST64(0x0008000200080800), CONST64(0x0008000008080800), CONST64(0x0008000208080800), + CONST64(0x0008000000000008), CONST64(0x0008000200000008), CONST64(0x0008000008000008), CONST64(0x0008000208000008), + CONST64(0x0008000000080008), CONST64(0x0008000200080008), CONST64(0x0008000008080008), CONST64(0x0008000208080008), + CONST64(0x0008000000000808), CONST64(0x0008000200000808), CONST64(0x0008000008000808), CONST64(0x0008000208000808), + CONST64(0x0008000000080808), CONST64(0x0008000200080808), CONST64(0x0008000008080808), CONST64(0x0008000208080808), + CONST64(0x0808000000000000), CONST64(0x0808000200000000), CONST64(0x0808000008000000), CONST64(0x0808000208000000), + CONST64(0x0808000000080000), CONST64(0x0808000200080000), CONST64(0x0808000008080000), CONST64(0x0808000208080000), + CONST64(0x0808000000000800), CONST64(0x0808000200000800), CONST64(0x0808000008000800), CONST64(0x0808000208000800), + CONST64(0x0808000000080800), CONST64(0x0808000200080800), CONST64(0x0808000008080800), CONST64(0x0808000208080800), + CONST64(0x0808000000000008), CONST64(0x0808000200000008), CONST64(0x0808000008000008), CONST64(0x0808000208000008), + CONST64(0x0808000000080008), CONST64(0x0808000200080008), CONST64(0x0808000008080008), CONST64(0x0808000208080008), + CONST64(0x0808000000000808), CONST64(0x0808000200000808), CONST64(0x0808000008000808), CONST64(0x0808000208000808), + CONST64(0x0808000000080808), CONST64(0x0808000200080808), CONST64(0x0808000008080808), CONST64(0x0808000208080808), + CONST64(0x0000080000000000), CONST64(0x0000080200000000), CONST64(0x0000080008000000), CONST64(0x0000080208000000), + CONST64(0x0000080000080000), CONST64(0x0000080200080000), CONST64(0x0000080008080000), CONST64(0x0000080208080000), + CONST64(0x0000080000000800), CONST64(0x0000080200000800), CONST64(0x0000080008000800), CONST64(0x0000080208000800), + CONST64(0x0000080000080800), CONST64(0x0000080200080800), CONST64(0x0000080008080800), CONST64(0x0000080208080800), + CONST64(0x0000080000000008), CONST64(0x0000080200000008), CONST64(0x0000080008000008), CONST64(0x0000080208000008), + CONST64(0x0000080000080008), CONST64(0x0000080200080008), CONST64(0x0000080008080008), CONST64(0x0000080208080008), + CONST64(0x0000080000000808), CONST64(0x0000080200000808), CONST64(0x0000080008000808), CONST64(0x0000080208000808), + CONST64(0x0000080000080808), CONST64(0x0000080200080808), CONST64(0x0000080008080808), CONST64(0x0000080208080808), + CONST64(0x0800080000000000), CONST64(0x0800080200000000), CONST64(0x0800080008000000), CONST64(0x0800080208000000), + CONST64(0x0800080000080000), CONST64(0x0800080200080000), CONST64(0x0800080008080000), CONST64(0x0800080208080000), + CONST64(0x0800080000000800), CONST64(0x0800080200000800), CONST64(0x0800080008000800), CONST64(0x0800080208000800), + CONST64(0x0800080000080800), CONST64(0x0800080200080800), CONST64(0x0800080008080800), CONST64(0x0800080208080800), + CONST64(0x0800080000000008), CONST64(0x0800080200000008), CONST64(0x0800080008000008), CONST64(0x0800080208000008), + CONST64(0x0800080000080008), CONST64(0x0800080200080008), CONST64(0x0800080008080008), CONST64(0x0800080208080008), + CONST64(0x0800080000000808), CONST64(0x0800080200000808), CONST64(0x0800080008000808), CONST64(0x0800080208000808), + CONST64(0x0800080000080808), CONST64(0x0800080200080808), CONST64(0x0800080008080808), CONST64(0x0800080208080808), + CONST64(0x0008080000000000), CONST64(0x0008080200000000), CONST64(0x0008080008000000), CONST64(0x0008080208000000), + CONST64(0x0008080000080000), CONST64(0x0008080200080000), CONST64(0x0008080008080000), CONST64(0x0008080208080000), + CONST64(0x0008080000000800), CONST64(0x0008080200000800), CONST64(0x0008080008000800), CONST64(0x0008080208000800), + CONST64(0x0008080000080800), CONST64(0x0008080200080800), CONST64(0x0008080008080800), CONST64(0x0008080208080800), + CONST64(0x0008080000000008), CONST64(0x0008080200000008), CONST64(0x0008080008000008), CONST64(0x0008080208000008), + CONST64(0x0008080000080008), CONST64(0x0008080200080008), CONST64(0x0008080008080008), CONST64(0x0008080208080008), + CONST64(0x0008080000000808), CONST64(0x0008080200000808), CONST64(0x0008080008000808), CONST64(0x0008080208000808), + CONST64(0x0008080000080808), CONST64(0x0008080200080808), CONST64(0x0008080008080808), CONST64(0x0008080208080808), + CONST64(0x0808080000000000), CONST64(0x0808080200000000), CONST64(0x0808080008000000), CONST64(0x0808080208000000), + CONST64(0x0808080000080000), CONST64(0x0808080200080000), CONST64(0x0808080008080000), CONST64(0x0808080208080000), + CONST64(0x0808080000000800), CONST64(0x0808080200000800), CONST64(0x0808080008000800), CONST64(0x0808080208000800), + CONST64(0x0808080000080800), CONST64(0x0808080200080800), CONST64(0x0808080008080800), CONST64(0x0808080208080800), + CONST64(0x0808080000000008), CONST64(0x0808080200000008), CONST64(0x0808080008000008), CONST64(0x0808080208000008), + CONST64(0x0808080000080008), CONST64(0x0808080200080008), CONST64(0x0808080008080008), CONST64(0x0808080208080008), + CONST64(0x0808080000000808), CONST64(0x0808080200000808), CONST64(0x0808080008000808), CONST64(0x0808080208000808), + CONST64(0x0808080000080808), CONST64(0x0808080200080808), CONST64(0x0808080008080808), CONST64(0x0808080208080808) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000000800000000), CONST64(0x0000000020000000), CONST64(0x0000000820000000), + CONST64(0x0000000000200000), CONST64(0x0000000800200000), CONST64(0x0000000020200000), CONST64(0x0000000820200000), + CONST64(0x0000000000002000), CONST64(0x0000000800002000), CONST64(0x0000000020002000), CONST64(0x0000000820002000), + CONST64(0x0000000000202000), CONST64(0x0000000800202000), CONST64(0x0000000020202000), CONST64(0x0000000820202000), + CONST64(0x0000000000000020), CONST64(0x0000000800000020), CONST64(0x0000000020000020), CONST64(0x0000000820000020), + CONST64(0x0000000000200020), CONST64(0x0000000800200020), CONST64(0x0000000020200020), CONST64(0x0000000820200020), + CONST64(0x0000000000002020), CONST64(0x0000000800002020), CONST64(0x0000000020002020), CONST64(0x0000000820002020), + CONST64(0x0000000000202020), CONST64(0x0000000800202020), CONST64(0x0000000020202020), CONST64(0x0000000820202020), + CONST64(0x2000000000000000), CONST64(0x2000000800000000), CONST64(0x2000000020000000), CONST64(0x2000000820000000), + CONST64(0x2000000000200000), CONST64(0x2000000800200000), CONST64(0x2000000020200000), CONST64(0x2000000820200000), + CONST64(0x2000000000002000), CONST64(0x2000000800002000), CONST64(0x2000000020002000), CONST64(0x2000000820002000), + CONST64(0x2000000000202000), CONST64(0x2000000800202000), CONST64(0x2000000020202000), CONST64(0x2000000820202000), + CONST64(0x2000000000000020), CONST64(0x2000000800000020), CONST64(0x2000000020000020), CONST64(0x2000000820000020), + CONST64(0x2000000000200020), CONST64(0x2000000800200020), CONST64(0x2000000020200020), CONST64(0x2000000820200020), + CONST64(0x2000000000002020), CONST64(0x2000000800002020), CONST64(0x2000000020002020), CONST64(0x2000000820002020), + CONST64(0x2000000000202020), CONST64(0x2000000800202020), CONST64(0x2000000020202020), CONST64(0x2000000820202020), + CONST64(0x0020000000000000), CONST64(0x0020000800000000), CONST64(0x0020000020000000), CONST64(0x0020000820000000), + CONST64(0x0020000000200000), CONST64(0x0020000800200000), CONST64(0x0020000020200000), CONST64(0x0020000820200000), + CONST64(0x0020000000002000), CONST64(0x0020000800002000), CONST64(0x0020000020002000), CONST64(0x0020000820002000), + CONST64(0x0020000000202000), CONST64(0x0020000800202000), CONST64(0x0020000020202000), CONST64(0x0020000820202000), + CONST64(0x0020000000000020), CONST64(0x0020000800000020), CONST64(0x0020000020000020), CONST64(0x0020000820000020), + CONST64(0x0020000000200020), CONST64(0x0020000800200020), CONST64(0x0020000020200020), CONST64(0x0020000820200020), + CONST64(0x0020000000002020), CONST64(0x0020000800002020), CONST64(0x0020000020002020), CONST64(0x0020000820002020), + CONST64(0x0020000000202020), CONST64(0x0020000800202020), CONST64(0x0020000020202020), CONST64(0x0020000820202020), + CONST64(0x2020000000000000), CONST64(0x2020000800000000), CONST64(0x2020000020000000), CONST64(0x2020000820000000), + CONST64(0x2020000000200000), CONST64(0x2020000800200000), CONST64(0x2020000020200000), CONST64(0x2020000820200000), + CONST64(0x2020000000002000), CONST64(0x2020000800002000), CONST64(0x2020000020002000), CONST64(0x2020000820002000), + CONST64(0x2020000000202000), CONST64(0x2020000800202000), CONST64(0x2020000020202000), CONST64(0x2020000820202000), + CONST64(0x2020000000000020), CONST64(0x2020000800000020), CONST64(0x2020000020000020), CONST64(0x2020000820000020), + CONST64(0x2020000000200020), CONST64(0x2020000800200020), CONST64(0x2020000020200020), CONST64(0x2020000820200020), + CONST64(0x2020000000002020), CONST64(0x2020000800002020), CONST64(0x2020000020002020), CONST64(0x2020000820002020), + CONST64(0x2020000000202020), CONST64(0x2020000800202020), CONST64(0x2020000020202020), CONST64(0x2020000820202020), + CONST64(0x0000200000000000), CONST64(0x0000200800000000), CONST64(0x0000200020000000), CONST64(0x0000200820000000), + CONST64(0x0000200000200000), CONST64(0x0000200800200000), CONST64(0x0000200020200000), CONST64(0x0000200820200000), + CONST64(0x0000200000002000), CONST64(0x0000200800002000), CONST64(0x0000200020002000), CONST64(0x0000200820002000), + CONST64(0x0000200000202000), CONST64(0x0000200800202000), CONST64(0x0000200020202000), CONST64(0x0000200820202000), + CONST64(0x0000200000000020), CONST64(0x0000200800000020), CONST64(0x0000200020000020), CONST64(0x0000200820000020), + CONST64(0x0000200000200020), CONST64(0x0000200800200020), CONST64(0x0000200020200020), CONST64(0x0000200820200020), + CONST64(0x0000200000002020), CONST64(0x0000200800002020), CONST64(0x0000200020002020), CONST64(0x0000200820002020), + CONST64(0x0000200000202020), CONST64(0x0000200800202020), CONST64(0x0000200020202020), CONST64(0x0000200820202020), + CONST64(0x2000200000000000), CONST64(0x2000200800000000), CONST64(0x2000200020000000), CONST64(0x2000200820000000), + CONST64(0x2000200000200000), CONST64(0x2000200800200000), CONST64(0x2000200020200000), CONST64(0x2000200820200000), + CONST64(0x2000200000002000), CONST64(0x2000200800002000), CONST64(0x2000200020002000), CONST64(0x2000200820002000), + CONST64(0x2000200000202000), CONST64(0x2000200800202000), CONST64(0x2000200020202000), CONST64(0x2000200820202000), + CONST64(0x2000200000000020), CONST64(0x2000200800000020), CONST64(0x2000200020000020), CONST64(0x2000200820000020), + CONST64(0x2000200000200020), CONST64(0x2000200800200020), CONST64(0x2000200020200020), CONST64(0x2000200820200020), + CONST64(0x2000200000002020), CONST64(0x2000200800002020), CONST64(0x2000200020002020), CONST64(0x2000200820002020), + CONST64(0x2000200000202020), CONST64(0x2000200800202020), CONST64(0x2000200020202020), CONST64(0x2000200820202020), + CONST64(0x0020200000000000), CONST64(0x0020200800000000), CONST64(0x0020200020000000), CONST64(0x0020200820000000), + CONST64(0x0020200000200000), CONST64(0x0020200800200000), CONST64(0x0020200020200000), CONST64(0x0020200820200000), + CONST64(0x0020200000002000), CONST64(0x0020200800002000), CONST64(0x0020200020002000), CONST64(0x0020200820002000), + CONST64(0x0020200000202000), CONST64(0x0020200800202000), CONST64(0x0020200020202000), CONST64(0x0020200820202000), + CONST64(0x0020200000000020), CONST64(0x0020200800000020), CONST64(0x0020200020000020), CONST64(0x0020200820000020), + CONST64(0x0020200000200020), CONST64(0x0020200800200020), CONST64(0x0020200020200020), CONST64(0x0020200820200020), + CONST64(0x0020200000002020), CONST64(0x0020200800002020), CONST64(0x0020200020002020), CONST64(0x0020200820002020), + CONST64(0x0020200000202020), CONST64(0x0020200800202020), CONST64(0x0020200020202020), CONST64(0x0020200820202020), + CONST64(0x2020200000000000), CONST64(0x2020200800000000), CONST64(0x2020200020000000), CONST64(0x2020200820000000), + CONST64(0x2020200000200000), CONST64(0x2020200800200000), CONST64(0x2020200020200000), CONST64(0x2020200820200000), + CONST64(0x2020200000002000), CONST64(0x2020200800002000), CONST64(0x2020200020002000), CONST64(0x2020200820002000), + CONST64(0x2020200000202000), CONST64(0x2020200800202000), CONST64(0x2020200020202000), CONST64(0x2020200820202000), + CONST64(0x2020200000000020), CONST64(0x2020200800000020), CONST64(0x2020200020000020), CONST64(0x2020200820000020), + CONST64(0x2020200000200020), CONST64(0x2020200800200020), CONST64(0x2020200020200020), CONST64(0x2020200820200020), + CONST64(0x2020200000002020), CONST64(0x2020200800002020), CONST64(0x2020200020002020), CONST64(0x2020200820002020), + CONST64(0x2020200000202020), CONST64(0x2020200800202020), CONST64(0x2020200020202020), CONST64(0x2020200820202020) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000002000000000), CONST64(0x0000000080000000), CONST64(0x0000002080000000), + CONST64(0x0000000000800000), CONST64(0x0000002000800000), CONST64(0x0000000080800000), CONST64(0x0000002080800000), + CONST64(0x0000000000008000), CONST64(0x0000002000008000), CONST64(0x0000000080008000), CONST64(0x0000002080008000), + CONST64(0x0000000000808000), CONST64(0x0000002000808000), CONST64(0x0000000080808000), CONST64(0x0000002080808000), + CONST64(0x0000000000000080), CONST64(0x0000002000000080), CONST64(0x0000000080000080), CONST64(0x0000002080000080), + CONST64(0x0000000000800080), CONST64(0x0000002000800080), CONST64(0x0000000080800080), CONST64(0x0000002080800080), + CONST64(0x0000000000008080), CONST64(0x0000002000008080), CONST64(0x0000000080008080), CONST64(0x0000002080008080), + CONST64(0x0000000000808080), CONST64(0x0000002000808080), CONST64(0x0000000080808080), CONST64(0x0000002080808080), + CONST64(0x8000000000000000), CONST64(0x8000002000000000), CONST64(0x8000000080000000), CONST64(0x8000002080000000), + CONST64(0x8000000000800000), CONST64(0x8000002000800000), CONST64(0x8000000080800000), CONST64(0x8000002080800000), + CONST64(0x8000000000008000), CONST64(0x8000002000008000), CONST64(0x8000000080008000), CONST64(0x8000002080008000), + CONST64(0x8000000000808000), CONST64(0x8000002000808000), CONST64(0x8000000080808000), CONST64(0x8000002080808000), + CONST64(0x8000000000000080), CONST64(0x8000002000000080), CONST64(0x8000000080000080), CONST64(0x8000002080000080), + CONST64(0x8000000000800080), CONST64(0x8000002000800080), CONST64(0x8000000080800080), CONST64(0x8000002080800080), + CONST64(0x8000000000008080), CONST64(0x8000002000008080), CONST64(0x8000000080008080), CONST64(0x8000002080008080), + CONST64(0x8000000000808080), CONST64(0x8000002000808080), CONST64(0x8000000080808080), CONST64(0x8000002080808080), + CONST64(0x0080000000000000), CONST64(0x0080002000000000), CONST64(0x0080000080000000), CONST64(0x0080002080000000), + CONST64(0x0080000000800000), CONST64(0x0080002000800000), CONST64(0x0080000080800000), CONST64(0x0080002080800000), + CONST64(0x0080000000008000), CONST64(0x0080002000008000), CONST64(0x0080000080008000), CONST64(0x0080002080008000), + CONST64(0x0080000000808000), CONST64(0x0080002000808000), CONST64(0x0080000080808000), CONST64(0x0080002080808000), + CONST64(0x0080000000000080), CONST64(0x0080002000000080), CONST64(0x0080000080000080), CONST64(0x0080002080000080), + CONST64(0x0080000000800080), CONST64(0x0080002000800080), CONST64(0x0080000080800080), CONST64(0x0080002080800080), + CONST64(0x0080000000008080), CONST64(0x0080002000008080), CONST64(0x0080000080008080), CONST64(0x0080002080008080), + CONST64(0x0080000000808080), CONST64(0x0080002000808080), CONST64(0x0080000080808080), CONST64(0x0080002080808080), + CONST64(0x8080000000000000), CONST64(0x8080002000000000), CONST64(0x8080000080000000), CONST64(0x8080002080000000), + CONST64(0x8080000000800000), CONST64(0x8080002000800000), CONST64(0x8080000080800000), CONST64(0x8080002080800000), + CONST64(0x8080000000008000), CONST64(0x8080002000008000), CONST64(0x8080000080008000), CONST64(0x8080002080008000), + CONST64(0x8080000000808000), CONST64(0x8080002000808000), CONST64(0x8080000080808000), CONST64(0x8080002080808000), + CONST64(0x8080000000000080), CONST64(0x8080002000000080), CONST64(0x8080000080000080), CONST64(0x8080002080000080), + CONST64(0x8080000000800080), CONST64(0x8080002000800080), CONST64(0x8080000080800080), CONST64(0x8080002080800080), + CONST64(0x8080000000008080), CONST64(0x8080002000008080), CONST64(0x8080000080008080), CONST64(0x8080002080008080), + CONST64(0x8080000000808080), CONST64(0x8080002000808080), CONST64(0x8080000080808080), CONST64(0x8080002080808080), + CONST64(0x0000800000000000), CONST64(0x0000802000000000), CONST64(0x0000800080000000), CONST64(0x0000802080000000), + CONST64(0x0000800000800000), CONST64(0x0000802000800000), CONST64(0x0000800080800000), CONST64(0x0000802080800000), + CONST64(0x0000800000008000), CONST64(0x0000802000008000), CONST64(0x0000800080008000), CONST64(0x0000802080008000), + CONST64(0x0000800000808000), CONST64(0x0000802000808000), CONST64(0x0000800080808000), CONST64(0x0000802080808000), + CONST64(0x0000800000000080), CONST64(0x0000802000000080), CONST64(0x0000800080000080), CONST64(0x0000802080000080), + CONST64(0x0000800000800080), CONST64(0x0000802000800080), CONST64(0x0000800080800080), CONST64(0x0000802080800080), + CONST64(0x0000800000008080), CONST64(0x0000802000008080), CONST64(0x0000800080008080), CONST64(0x0000802080008080), + CONST64(0x0000800000808080), CONST64(0x0000802000808080), CONST64(0x0000800080808080), CONST64(0x0000802080808080), + CONST64(0x8000800000000000), CONST64(0x8000802000000000), CONST64(0x8000800080000000), CONST64(0x8000802080000000), + CONST64(0x8000800000800000), CONST64(0x8000802000800000), CONST64(0x8000800080800000), CONST64(0x8000802080800000), + CONST64(0x8000800000008000), CONST64(0x8000802000008000), CONST64(0x8000800080008000), CONST64(0x8000802080008000), + CONST64(0x8000800000808000), CONST64(0x8000802000808000), CONST64(0x8000800080808000), CONST64(0x8000802080808000), + CONST64(0x8000800000000080), CONST64(0x8000802000000080), CONST64(0x8000800080000080), CONST64(0x8000802080000080), + CONST64(0x8000800000800080), CONST64(0x8000802000800080), CONST64(0x8000800080800080), CONST64(0x8000802080800080), + CONST64(0x8000800000008080), CONST64(0x8000802000008080), CONST64(0x8000800080008080), CONST64(0x8000802080008080), + CONST64(0x8000800000808080), CONST64(0x8000802000808080), CONST64(0x8000800080808080), CONST64(0x8000802080808080), + CONST64(0x0080800000000000), CONST64(0x0080802000000000), CONST64(0x0080800080000000), CONST64(0x0080802080000000), + CONST64(0x0080800000800000), CONST64(0x0080802000800000), CONST64(0x0080800080800000), CONST64(0x0080802080800000), + CONST64(0x0080800000008000), CONST64(0x0080802000008000), CONST64(0x0080800080008000), CONST64(0x0080802080008000), + CONST64(0x0080800000808000), CONST64(0x0080802000808000), CONST64(0x0080800080808000), CONST64(0x0080802080808000), + CONST64(0x0080800000000080), CONST64(0x0080802000000080), CONST64(0x0080800080000080), CONST64(0x0080802080000080), + CONST64(0x0080800000800080), CONST64(0x0080802000800080), CONST64(0x0080800080800080), CONST64(0x0080802080800080), + CONST64(0x0080800000008080), CONST64(0x0080802000008080), CONST64(0x0080800080008080), CONST64(0x0080802080008080), + CONST64(0x0080800000808080), CONST64(0x0080802000808080), CONST64(0x0080800080808080), CONST64(0x0080802080808080), + CONST64(0x8080800000000000), CONST64(0x8080802000000000), CONST64(0x8080800080000000), CONST64(0x8080802080000000), + CONST64(0x8080800000800000), CONST64(0x8080802000800000), CONST64(0x8080800080800000), CONST64(0x8080802080800000), + CONST64(0x8080800000008000), CONST64(0x8080802000008000), CONST64(0x8080800080008000), CONST64(0x8080802080008000), + CONST64(0x8080800000808000), CONST64(0x8080802000808000), CONST64(0x8080800080808000), CONST64(0x8080802080808000), + CONST64(0x8080800000000080), CONST64(0x8080802000000080), CONST64(0x8080800080000080), CONST64(0x8080802080000080), + CONST64(0x8080800000800080), CONST64(0x8080802000800080), CONST64(0x8080800080800080), CONST64(0x8080802080800080), + CONST64(0x8080800000008080), CONST64(0x8080802000008080), CONST64(0x8080800080008080), CONST64(0x8080802080008080), + CONST64(0x8080800000808080), CONST64(0x8080802000808080), CONST64(0x8080800080808080), CONST64(0x8080802080808080) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000004000000000), CONST64(0x0000000001000000), CONST64(0x0000004001000000), + CONST64(0x0000000000010000), CONST64(0x0000004000010000), CONST64(0x0000000001010000), CONST64(0x0000004001010000), + CONST64(0x0000000000000100), CONST64(0x0000004000000100), CONST64(0x0000000001000100), CONST64(0x0000004001000100), + CONST64(0x0000000000010100), CONST64(0x0000004000010100), CONST64(0x0000000001010100), CONST64(0x0000004001010100), + CONST64(0x0000000000000001), CONST64(0x0000004000000001), CONST64(0x0000000001000001), CONST64(0x0000004001000001), + CONST64(0x0000000000010001), CONST64(0x0000004000010001), CONST64(0x0000000001010001), CONST64(0x0000004001010001), + CONST64(0x0000000000000101), CONST64(0x0000004000000101), CONST64(0x0000000001000101), CONST64(0x0000004001000101), + CONST64(0x0000000000010101), CONST64(0x0000004000010101), CONST64(0x0000000001010101), CONST64(0x0000004001010101), + CONST64(0x0100000000000000), CONST64(0x0100004000000000), CONST64(0x0100000001000000), CONST64(0x0100004001000000), + CONST64(0x0100000000010000), CONST64(0x0100004000010000), CONST64(0x0100000001010000), CONST64(0x0100004001010000), + CONST64(0x0100000000000100), CONST64(0x0100004000000100), CONST64(0x0100000001000100), CONST64(0x0100004001000100), + CONST64(0x0100000000010100), CONST64(0x0100004000010100), CONST64(0x0100000001010100), CONST64(0x0100004001010100), + CONST64(0x0100000000000001), CONST64(0x0100004000000001), CONST64(0x0100000001000001), CONST64(0x0100004001000001), + CONST64(0x0100000000010001), CONST64(0x0100004000010001), CONST64(0x0100000001010001), CONST64(0x0100004001010001), + CONST64(0x0100000000000101), CONST64(0x0100004000000101), CONST64(0x0100000001000101), CONST64(0x0100004001000101), + CONST64(0x0100000000010101), CONST64(0x0100004000010101), CONST64(0x0100000001010101), CONST64(0x0100004001010101), + CONST64(0x0001000000000000), CONST64(0x0001004000000000), CONST64(0x0001000001000000), CONST64(0x0001004001000000), + CONST64(0x0001000000010000), CONST64(0x0001004000010000), CONST64(0x0001000001010000), CONST64(0x0001004001010000), + CONST64(0x0001000000000100), CONST64(0x0001004000000100), CONST64(0x0001000001000100), CONST64(0x0001004001000100), + CONST64(0x0001000000010100), CONST64(0x0001004000010100), CONST64(0x0001000001010100), CONST64(0x0001004001010100), + CONST64(0x0001000000000001), CONST64(0x0001004000000001), CONST64(0x0001000001000001), CONST64(0x0001004001000001), + CONST64(0x0001000000010001), CONST64(0x0001004000010001), CONST64(0x0001000001010001), CONST64(0x0001004001010001), + CONST64(0x0001000000000101), CONST64(0x0001004000000101), CONST64(0x0001000001000101), CONST64(0x0001004001000101), + CONST64(0x0001000000010101), CONST64(0x0001004000010101), CONST64(0x0001000001010101), CONST64(0x0001004001010101), + CONST64(0x0101000000000000), CONST64(0x0101004000000000), CONST64(0x0101000001000000), CONST64(0x0101004001000000), + CONST64(0x0101000000010000), CONST64(0x0101004000010000), CONST64(0x0101000001010000), CONST64(0x0101004001010000), + CONST64(0x0101000000000100), CONST64(0x0101004000000100), CONST64(0x0101000001000100), CONST64(0x0101004001000100), + CONST64(0x0101000000010100), CONST64(0x0101004000010100), CONST64(0x0101000001010100), CONST64(0x0101004001010100), + CONST64(0x0101000000000001), CONST64(0x0101004000000001), CONST64(0x0101000001000001), CONST64(0x0101004001000001), + CONST64(0x0101000000010001), CONST64(0x0101004000010001), CONST64(0x0101000001010001), CONST64(0x0101004001010001), + CONST64(0x0101000000000101), CONST64(0x0101004000000101), CONST64(0x0101000001000101), CONST64(0x0101004001000101), + CONST64(0x0101000000010101), CONST64(0x0101004000010101), CONST64(0x0101000001010101), CONST64(0x0101004001010101), + CONST64(0x0000010000000000), CONST64(0x0000014000000000), CONST64(0x0000010001000000), CONST64(0x0000014001000000), + CONST64(0x0000010000010000), CONST64(0x0000014000010000), CONST64(0x0000010001010000), CONST64(0x0000014001010000), + CONST64(0x0000010000000100), CONST64(0x0000014000000100), CONST64(0x0000010001000100), CONST64(0x0000014001000100), + CONST64(0x0000010000010100), CONST64(0x0000014000010100), CONST64(0x0000010001010100), CONST64(0x0000014001010100), + CONST64(0x0000010000000001), CONST64(0x0000014000000001), CONST64(0x0000010001000001), CONST64(0x0000014001000001), + CONST64(0x0000010000010001), CONST64(0x0000014000010001), CONST64(0x0000010001010001), CONST64(0x0000014001010001), + CONST64(0x0000010000000101), CONST64(0x0000014000000101), CONST64(0x0000010001000101), CONST64(0x0000014001000101), + CONST64(0x0000010000010101), CONST64(0x0000014000010101), CONST64(0x0000010001010101), CONST64(0x0000014001010101), + CONST64(0x0100010000000000), CONST64(0x0100014000000000), CONST64(0x0100010001000000), CONST64(0x0100014001000000), + CONST64(0x0100010000010000), CONST64(0x0100014000010000), CONST64(0x0100010001010000), CONST64(0x0100014001010000), + CONST64(0x0100010000000100), CONST64(0x0100014000000100), CONST64(0x0100010001000100), CONST64(0x0100014001000100), + CONST64(0x0100010000010100), CONST64(0x0100014000010100), CONST64(0x0100010001010100), CONST64(0x0100014001010100), + CONST64(0x0100010000000001), CONST64(0x0100014000000001), CONST64(0x0100010001000001), CONST64(0x0100014001000001), + CONST64(0x0100010000010001), CONST64(0x0100014000010001), CONST64(0x0100010001010001), CONST64(0x0100014001010001), + CONST64(0x0100010000000101), CONST64(0x0100014000000101), CONST64(0x0100010001000101), CONST64(0x0100014001000101), + CONST64(0x0100010000010101), CONST64(0x0100014000010101), CONST64(0x0100010001010101), CONST64(0x0100014001010101), + CONST64(0x0001010000000000), CONST64(0x0001014000000000), CONST64(0x0001010001000000), CONST64(0x0001014001000000), + CONST64(0x0001010000010000), CONST64(0x0001014000010000), CONST64(0x0001010001010000), CONST64(0x0001014001010000), + CONST64(0x0001010000000100), CONST64(0x0001014000000100), CONST64(0x0001010001000100), CONST64(0x0001014001000100), + CONST64(0x0001010000010100), CONST64(0x0001014000010100), CONST64(0x0001010001010100), CONST64(0x0001014001010100), + CONST64(0x0001010000000001), CONST64(0x0001014000000001), CONST64(0x0001010001000001), CONST64(0x0001014001000001), + CONST64(0x0001010000010001), CONST64(0x0001014000010001), CONST64(0x0001010001010001), CONST64(0x0001014001010001), + CONST64(0x0001010000000101), CONST64(0x0001014000000101), CONST64(0x0001010001000101), CONST64(0x0001014001000101), + CONST64(0x0001010000010101), CONST64(0x0001014000010101), CONST64(0x0001010001010101), CONST64(0x0001014001010101), + CONST64(0x0101010000000000), CONST64(0x0101014000000000), CONST64(0x0101010001000000), CONST64(0x0101014001000000), + CONST64(0x0101010000010000), CONST64(0x0101014000010000), CONST64(0x0101010001010000), CONST64(0x0101014001010000), + CONST64(0x0101010000000100), CONST64(0x0101014000000100), CONST64(0x0101010001000100), CONST64(0x0101014001000100), + CONST64(0x0101010000010100), CONST64(0x0101014000010100), CONST64(0x0101010001010100), CONST64(0x0101014001010100), + CONST64(0x0101010000000001), CONST64(0x0101014000000001), CONST64(0x0101010001000001), CONST64(0x0101014001000001), + CONST64(0x0101010000010001), CONST64(0x0101014000010001), CONST64(0x0101010001010001), CONST64(0x0101014001010001), + CONST64(0x0101010000000101), CONST64(0x0101014000000101), CONST64(0x0101010001000101), CONST64(0x0101014001000101), + CONST64(0x0101010000010101), CONST64(0x0101014000010101), CONST64(0x0101010001010101), CONST64(0x0101014001010101) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000000100000000), CONST64(0x0000000004000000), CONST64(0x0000000104000000), + CONST64(0x0000000000040000), CONST64(0x0000000100040000), CONST64(0x0000000004040000), CONST64(0x0000000104040000), + CONST64(0x0000000000000400), CONST64(0x0000000100000400), CONST64(0x0000000004000400), CONST64(0x0000000104000400), + CONST64(0x0000000000040400), CONST64(0x0000000100040400), CONST64(0x0000000004040400), CONST64(0x0000000104040400), + CONST64(0x0000000000000004), CONST64(0x0000000100000004), CONST64(0x0000000004000004), CONST64(0x0000000104000004), + CONST64(0x0000000000040004), CONST64(0x0000000100040004), CONST64(0x0000000004040004), CONST64(0x0000000104040004), + CONST64(0x0000000000000404), CONST64(0x0000000100000404), CONST64(0x0000000004000404), CONST64(0x0000000104000404), + CONST64(0x0000000000040404), CONST64(0x0000000100040404), CONST64(0x0000000004040404), CONST64(0x0000000104040404), + CONST64(0x0400000000000000), CONST64(0x0400000100000000), CONST64(0x0400000004000000), CONST64(0x0400000104000000), + CONST64(0x0400000000040000), CONST64(0x0400000100040000), CONST64(0x0400000004040000), CONST64(0x0400000104040000), + CONST64(0x0400000000000400), CONST64(0x0400000100000400), CONST64(0x0400000004000400), CONST64(0x0400000104000400), + CONST64(0x0400000000040400), CONST64(0x0400000100040400), CONST64(0x0400000004040400), CONST64(0x0400000104040400), + CONST64(0x0400000000000004), CONST64(0x0400000100000004), CONST64(0x0400000004000004), CONST64(0x0400000104000004), + CONST64(0x0400000000040004), CONST64(0x0400000100040004), CONST64(0x0400000004040004), CONST64(0x0400000104040004), + CONST64(0x0400000000000404), CONST64(0x0400000100000404), CONST64(0x0400000004000404), CONST64(0x0400000104000404), + CONST64(0x0400000000040404), CONST64(0x0400000100040404), CONST64(0x0400000004040404), CONST64(0x0400000104040404), + CONST64(0x0004000000000000), CONST64(0x0004000100000000), CONST64(0x0004000004000000), CONST64(0x0004000104000000), + CONST64(0x0004000000040000), CONST64(0x0004000100040000), CONST64(0x0004000004040000), CONST64(0x0004000104040000), + CONST64(0x0004000000000400), CONST64(0x0004000100000400), CONST64(0x0004000004000400), CONST64(0x0004000104000400), + CONST64(0x0004000000040400), CONST64(0x0004000100040400), CONST64(0x0004000004040400), CONST64(0x0004000104040400), + CONST64(0x0004000000000004), CONST64(0x0004000100000004), CONST64(0x0004000004000004), CONST64(0x0004000104000004), + CONST64(0x0004000000040004), CONST64(0x0004000100040004), CONST64(0x0004000004040004), CONST64(0x0004000104040004), + CONST64(0x0004000000000404), CONST64(0x0004000100000404), CONST64(0x0004000004000404), CONST64(0x0004000104000404), + CONST64(0x0004000000040404), CONST64(0x0004000100040404), CONST64(0x0004000004040404), CONST64(0x0004000104040404), + CONST64(0x0404000000000000), CONST64(0x0404000100000000), CONST64(0x0404000004000000), CONST64(0x0404000104000000), + CONST64(0x0404000000040000), CONST64(0x0404000100040000), CONST64(0x0404000004040000), CONST64(0x0404000104040000), + CONST64(0x0404000000000400), CONST64(0x0404000100000400), CONST64(0x0404000004000400), CONST64(0x0404000104000400), + CONST64(0x0404000000040400), CONST64(0x0404000100040400), CONST64(0x0404000004040400), CONST64(0x0404000104040400), + CONST64(0x0404000000000004), CONST64(0x0404000100000004), CONST64(0x0404000004000004), CONST64(0x0404000104000004), + CONST64(0x0404000000040004), CONST64(0x0404000100040004), CONST64(0x0404000004040004), CONST64(0x0404000104040004), + CONST64(0x0404000000000404), CONST64(0x0404000100000404), CONST64(0x0404000004000404), CONST64(0x0404000104000404), + CONST64(0x0404000000040404), CONST64(0x0404000100040404), CONST64(0x0404000004040404), CONST64(0x0404000104040404), + CONST64(0x0000040000000000), CONST64(0x0000040100000000), CONST64(0x0000040004000000), CONST64(0x0000040104000000), + CONST64(0x0000040000040000), CONST64(0x0000040100040000), CONST64(0x0000040004040000), CONST64(0x0000040104040000), + CONST64(0x0000040000000400), CONST64(0x0000040100000400), CONST64(0x0000040004000400), CONST64(0x0000040104000400), + CONST64(0x0000040000040400), CONST64(0x0000040100040400), CONST64(0x0000040004040400), CONST64(0x0000040104040400), + CONST64(0x0000040000000004), CONST64(0x0000040100000004), CONST64(0x0000040004000004), CONST64(0x0000040104000004), + CONST64(0x0000040000040004), CONST64(0x0000040100040004), CONST64(0x0000040004040004), CONST64(0x0000040104040004), + CONST64(0x0000040000000404), CONST64(0x0000040100000404), CONST64(0x0000040004000404), CONST64(0x0000040104000404), + CONST64(0x0000040000040404), CONST64(0x0000040100040404), CONST64(0x0000040004040404), CONST64(0x0000040104040404), + CONST64(0x0400040000000000), CONST64(0x0400040100000000), CONST64(0x0400040004000000), CONST64(0x0400040104000000), + CONST64(0x0400040000040000), CONST64(0x0400040100040000), CONST64(0x0400040004040000), CONST64(0x0400040104040000), + CONST64(0x0400040000000400), CONST64(0x0400040100000400), CONST64(0x0400040004000400), CONST64(0x0400040104000400), + CONST64(0x0400040000040400), CONST64(0x0400040100040400), CONST64(0x0400040004040400), CONST64(0x0400040104040400), + CONST64(0x0400040000000004), CONST64(0x0400040100000004), CONST64(0x0400040004000004), CONST64(0x0400040104000004), + CONST64(0x0400040000040004), CONST64(0x0400040100040004), CONST64(0x0400040004040004), CONST64(0x0400040104040004), + CONST64(0x0400040000000404), CONST64(0x0400040100000404), CONST64(0x0400040004000404), CONST64(0x0400040104000404), + CONST64(0x0400040000040404), CONST64(0x0400040100040404), CONST64(0x0400040004040404), CONST64(0x0400040104040404), + CONST64(0x0004040000000000), CONST64(0x0004040100000000), CONST64(0x0004040004000000), CONST64(0x0004040104000000), + CONST64(0x0004040000040000), CONST64(0x0004040100040000), CONST64(0x0004040004040000), CONST64(0x0004040104040000), + CONST64(0x0004040000000400), CONST64(0x0004040100000400), CONST64(0x0004040004000400), CONST64(0x0004040104000400), + CONST64(0x0004040000040400), CONST64(0x0004040100040400), CONST64(0x0004040004040400), CONST64(0x0004040104040400), + CONST64(0x0004040000000004), CONST64(0x0004040100000004), CONST64(0x0004040004000004), CONST64(0x0004040104000004), + CONST64(0x0004040000040004), CONST64(0x0004040100040004), CONST64(0x0004040004040004), CONST64(0x0004040104040004), + CONST64(0x0004040000000404), CONST64(0x0004040100000404), CONST64(0x0004040004000404), CONST64(0x0004040104000404), + CONST64(0x0004040000040404), CONST64(0x0004040100040404), CONST64(0x0004040004040404), CONST64(0x0004040104040404), + CONST64(0x0404040000000000), CONST64(0x0404040100000000), CONST64(0x0404040004000000), CONST64(0x0404040104000000), + CONST64(0x0404040000040000), CONST64(0x0404040100040000), CONST64(0x0404040004040000), CONST64(0x0404040104040000), + CONST64(0x0404040000000400), CONST64(0x0404040100000400), CONST64(0x0404040004000400), CONST64(0x0404040104000400), + CONST64(0x0404040000040400), CONST64(0x0404040100040400), CONST64(0x0404040004040400), CONST64(0x0404040104040400), + CONST64(0x0404040000000004), CONST64(0x0404040100000004), CONST64(0x0404040004000004), CONST64(0x0404040104000004), + CONST64(0x0404040000040004), CONST64(0x0404040100040004), CONST64(0x0404040004040004), CONST64(0x0404040104040004), + CONST64(0x0404040000000404), CONST64(0x0404040100000404), CONST64(0x0404040004000404), CONST64(0x0404040104000404), + CONST64(0x0404040000040404), CONST64(0x0404040100040404), CONST64(0x0404040004040404), CONST64(0x0404040104040404) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000000400000000), CONST64(0x0000000010000000), CONST64(0x0000000410000000), + CONST64(0x0000000000100000), CONST64(0x0000000400100000), CONST64(0x0000000010100000), CONST64(0x0000000410100000), + CONST64(0x0000000000001000), CONST64(0x0000000400001000), CONST64(0x0000000010001000), CONST64(0x0000000410001000), + CONST64(0x0000000000101000), CONST64(0x0000000400101000), CONST64(0x0000000010101000), CONST64(0x0000000410101000), + CONST64(0x0000000000000010), CONST64(0x0000000400000010), CONST64(0x0000000010000010), CONST64(0x0000000410000010), + CONST64(0x0000000000100010), CONST64(0x0000000400100010), CONST64(0x0000000010100010), CONST64(0x0000000410100010), + CONST64(0x0000000000001010), CONST64(0x0000000400001010), CONST64(0x0000000010001010), CONST64(0x0000000410001010), + CONST64(0x0000000000101010), CONST64(0x0000000400101010), CONST64(0x0000000010101010), CONST64(0x0000000410101010), + CONST64(0x1000000000000000), CONST64(0x1000000400000000), CONST64(0x1000000010000000), CONST64(0x1000000410000000), + CONST64(0x1000000000100000), CONST64(0x1000000400100000), CONST64(0x1000000010100000), CONST64(0x1000000410100000), + CONST64(0x1000000000001000), CONST64(0x1000000400001000), CONST64(0x1000000010001000), CONST64(0x1000000410001000), + CONST64(0x1000000000101000), CONST64(0x1000000400101000), CONST64(0x1000000010101000), CONST64(0x1000000410101000), + CONST64(0x1000000000000010), CONST64(0x1000000400000010), CONST64(0x1000000010000010), CONST64(0x1000000410000010), + CONST64(0x1000000000100010), CONST64(0x1000000400100010), CONST64(0x1000000010100010), CONST64(0x1000000410100010), + CONST64(0x1000000000001010), CONST64(0x1000000400001010), CONST64(0x1000000010001010), CONST64(0x1000000410001010), + CONST64(0x1000000000101010), CONST64(0x1000000400101010), CONST64(0x1000000010101010), CONST64(0x1000000410101010), + CONST64(0x0010000000000000), CONST64(0x0010000400000000), CONST64(0x0010000010000000), CONST64(0x0010000410000000), + CONST64(0x0010000000100000), CONST64(0x0010000400100000), CONST64(0x0010000010100000), CONST64(0x0010000410100000), + CONST64(0x0010000000001000), CONST64(0x0010000400001000), CONST64(0x0010000010001000), CONST64(0x0010000410001000), + CONST64(0x0010000000101000), CONST64(0x0010000400101000), CONST64(0x0010000010101000), CONST64(0x0010000410101000), + CONST64(0x0010000000000010), CONST64(0x0010000400000010), CONST64(0x0010000010000010), CONST64(0x0010000410000010), + CONST64(0x0010000000100010), CONST64(0x0010000400100010), CONST64(0x0010000010100010), CONST64(0x0010000410100010), + CONST64(0x0010000000001010), CONST64(0x0010000400001010), CONST64(0x0010000010001010), CONST64(0x0010000410001010), + CONST64(0x0010000000101010), CONST64(0x0010000400101010), CONST64(0x0010000010101010), CONST64(0x0010000410101010), + CONST64(0x1010000000000000), CONST64(0x1010000400000000), CONST64(0x1010000010000000), CONST64(0x1010000410000000), + CONST64(0x1010000000100000), CONST64(0x1010000400100000), CONST64(0x1010000010100000), CONST64(0x1010000410100000), + CONST64(0x1010000000001000), CONST64(0x1010000400001000), CONST64(0x1010000010001000), CONST64(0x1010000410001000), + CONST64(0x1010000000101000), CONST64(0x1010000400101000), CONST64(0x1010000010101000), CONST64(0x1010000410101000), + CONST64(0x1010000000000010), CONST64(0x1010000400000010), CONST64(0x1010000010000010), CONST64(0x1010000410000010), + CONST64(0x1010000000100010), CONST64(0x1010000400100010), CONST64(0x1010000010100010), CONST64(0x1010000410100010), + CONST64(0x1010000000001010), CONST64(0x1010000400001010), CONST64(0x1010000010001010), CONST64(0x1010000410001010), + CONST64(0x1010000000101010), CONST64(0x1010000400101010), CONST64(0x1010000010101010), CONST64(0x1010000410101010), + CONST64(0x0000100000000000), CONST64(0x0000100400000000), CONST64(0x0000100010000000), CONST64(0x0000100410000000), + CONST64(0x0000100000100000), CONST64(0x0000100400100000), CONST64(0x0000100010100000), CONST64(0x0000100410100000), + CONST64(0x0000100000001000), CONST64(0x0000100400001000), CONST64(0x0000100010001000), CONST64(0x0000100410001000), + CONST64(0x0000100000101000), CONST64(0x0000100400101000), CONST64(0x0000100010101000), CONST64(0x0000100410101000), + CONST64(0x0000100000000010), CONST64(0x0000100400000010), CONST64(0x0000100010000010), CONST64(0x0000100410000010), + CONST64(0x0000100000100010), CONST64(0x0000100400100010), CONST64(0x0000100010100010), CONST64(0x0000100410100010), + CONST64(0x0000100000001010), CONST64(0x0000100400001010), CONST64(0x0000100010001010), CONST64(0x0000100410001010), + CONST64(0x0000100000101010), CONST64(0x0000100400101010), CONST64(0x0000100010101010), CONST64(0x0000100410101010), + CONST64(0x1000100000000000), CONST64(0x1000100400000000), CONST64(0x1000100010000000), CONST64(0x1000100410000000), + CONST64(0x1000100000100000), CONST64(0x1000100400100000), CONST64(0x1000100010100000), CONST64(0x1000100410100000), + CONST64(0x1000100000001000), CONST64(0x1000100400001000), CONST64(0x1000100010001000), CONST64(0x1000100410001000), + CONST64(0x1000100000101000), CONST64(0x1000100400101000), CONST64(0x1000100010101000), CONST64(0x1000100410101000), + CONST64(0x1000100000000010), CONST64(0x1000100400000010), CONST64(0x1000100010000010), CONST64(0x1000100410000010), + CONST64(0x1000100000100010), CONST64(0x1000100400100010), CONST64(0x1000100010100010), CONST64(0x1000100410100010), + CONST64(0x1000100000001010), CONST64(0x1000100400001010), CONST64(0x1000100010001010), CONST64(0x1000100410001010), + CONST64(0x1000100000101010), CONST64(0x1000100400101010), CONST64(0x1000100010101010), CONST64(0x1000100410101010), + CONST64(0x0010100000000000), CONST64(0x0010100400000000), CONST64(0x0010100010000000), CONST64(0x0010100410000000), + CONST64(0x0010100000100000), CONST64(0x0010100400100000), CONST64(0x0010100010100000), CONST64(0x0010100410100000), + CONST64(0x0010100000001000), CONST64(0x0010100400001000), CONST64(0x0010100010001000), CONST64(0x0010100410001000), + CONST64(0x0010100000101000), CONST64(0x0010100400101000), CONST64(0x0010100010101000), CONST64(0x0010100410101000), + CONST64(0x0010100000000010), CONST64(0x0010100400000010), CONST64(0x0010100010000010), CONST64(0x0010100410000010), + CONST64(0x0010100000100010), CONST64(0x0010100400100010), CONST64(0x0010100010100010), CONST64(0x0010100410100010), + CONST64(0x0010100000001010), CONST64(0x0010100400001010), CONST64(0x0010100010001010), CONST64(0x0010100410001010), + CONST64(0x0010100000101010), CONST64(0x0010100400101010), CONST64(0x0010100010101010), CONST64(0x0010100410101010), + CONST64(0x1010100000000000), CONST64(0x1010100400000000), CONST64(0x1010100010000000), CONST64(0x1010100410000000), + CONST64(0x1010100000100000), CONST64(0x1010100400100000), CONST64(0x1010100010100000), CONST64(0x1010100410100000), + CONST64(0x1010100000001000), CONST64(0x1010100400001000), CONST64(0x1010100010001000), CONST64(0x1010100410001000), + CONST64(0x1010100000101000), CONST64(0x1010100400101000), CONST64(0x1010100010101000), CONST64(0x1010100410101000), + CONST64(0x1010100000000010), CONST64(0x1010100400000010), CONST64(0x1010100010000010), CONST64(0x1010100410000010), + CONST64(0x1010100000100010), CONST64(0x1010100400100010), CONST64(0x1010100010100010), CONST64(0x1010100410100010), + CONST64(0x1010100000001010), CONST64(0x1010100400001010), CONST64(0x1010100010001010), CONST64(0x1010100410001010), + CONST64(0x1010100000101010), CONST64(0x1010100400101010), CONST64(0x1010100010101010), CONST64(0x1010100410101010) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000001000000000), CONST64(0x0000000040000000), CONST64(0x0000001040000000), + CONST64(0x0000000000400000), CONST64(0x0000001000400000), CONST64(0x0000000040400000), CONST64(0x0000001040400000), + CONST64(0x0000000000004000), CONST64(0x0000001000004000), CONST64(0x0000000040004000), CONST64(0x0000001040004000), + CONST64(0x0000000000404000), CONST64(0x0000001000404000), CONST64(0x0000000040404000), CONST64(0x0000001040404000), + CONST64(0x0000000000000040), CONST64(0x0000001000000040), CONST64(0x0000000040000040), CONST64(0x0000001040000040), + CONST64(0x0000000000400040), CONST64(0x0000001000400040), CONST64(0x0000000040400040), CONST64(0x0000001040400040), + CONST64(0x0000000000004040), CONST64(0x0000001000004040), CONST64(0x0000000040004040), CONST64(0x0000001040004040), + CONST64(0x0000000000404040), CONST64(0x0000001000404040), CONST64(0x0000000040404040), CONST64(0x0000001040404040), + CONST64(0x4000000000000000), CONST64(0x4000001000000000), CONST64(0x4000000040000000), CONST64(0x4000001040000000), + CONST64(0x4000000000400000), CONST64(0x4000001000400000), CONST64(0x4000000040400000), CONST64(0x4000001040400000), + CONST64(0x4000000000004000), CONST64(0x4000001000004000), CONST64(0x4000000040004000), CONST64(0x4000001040004000), + CONST64(0x4000000000404000), CONST64(0x4000001000404000), CONST64(0x4000000040404000), CONST64(0x4000001040404000), + CONST64(0x4000000000000040), CONST64(0x4000001000000040), CONST64(0x4000000040000040), CONST64(0x4000001040000040), + CONST64(0x4000000000400040), CONST64(0x4000001000400040), CONST64(0x4000000040400040), CONST64(0x4000001040400040), + CONST64(0x4000000000004040), CONST64(0x4000001000004040), CONST64(0x4000000040004040), CONST64(0x4000001040004040), + CONST64(0x4000000000404040), CONST64(0x4000001000404040), CONST64(0x4000000040404040), CONST64(0x4000001040404040), + CONST64(0x0040000000000000), CONST64(0x0040001000000000), CONST64(0x0040000040000000), CONST64(0x0040001040000000), + CONST64(0x0040000000400000), CONST64(0x0040001000400000), CONST64(0x0040000040400000), CONST64(0x0040001040400000), + CONST64(0x0040000000004000), CONST64(0x0040001000004000), CONST64(0x0040000040004000), CONST64(0x0040001040004000), + CONST64(0x0040000000404000), CONST64(0x0040001000404000), CONST64(0x0040000040404000), CONST64(0x0040001040404000), + CONST64(0x0040000000000040), CONST64(0x0040001000000040), CONST64(0x0040000040000040), CONST64(0x0040001040000040), + CONST64(0x0040000000400040), CONST64(0x0040001000400040), CONST64(0x0040000040400040), CONST64(0x0040001040400040), + CONST64(0x0040000000004040), CONST64(0x0040001000004040), CONST64(0x0040000040004040), CONST64(0x0040001040004040), + CONST64(0x0040000000404040), CONST64(0x0040001000404040), CONST64(0x0040000040404040), CONST64(0x0040001040404040), + CONST64(0x4040000000000000), CONST64(0x4040001000000000), CONST64(0x4040000040000000), CONST64(0x4040001040000000), + CONST64(0x4040000000400000), CONST64(0x4040001000400000), CONST64(0x4040000040400000), CONST64(0x4040001040400000), + CONST64(0x4040000000004000), CONST64(0x4040001000004000), CONST64(0x4040000040004000), CONST64(0x4040001040004000), + CONST64(0x4040000000404000), CONST64(0x4040001000404000), CONST64(0x4040000040404000), CONST64(0x4040001040404000), + CONST64(0x4040000000000040), CONST64(0x4040001000000040), CONST64(0x4040000040000040), CONST64(0x4040001040000040), + CONST64(0x4040000000400040), CONST64(0x4040001000400040), CONST64(0x4040000040400040), CONST64(0x4040001040400040), + CONST64(0x4040000000004040), CONST64(0x4040001000004040), CONST64(0x4040000040004040), CONST64(0x4040001040004040), + CONST64(0x4040000000404040), CONST64(0x4040001000404040), CONST64(0x4040000040404040), CONST64(0x4040001040404040), + CONST64(0x0000400000000000), CONST64(0x0000401000000000), CONST64(0x0000400040000000), CONST64(0x0000401040000000), + CONST64(0x0000400000400000), CONST64(0x0000401000400000), CONST64(0x0000400040400000), CONST64(0x0000401040400000), + CONST64(0x0000400000004000), CONST64(0x0000401000004000), CONST64(0x0000400040004000), CONST64(0x0000401040004000), + CONST64(0x0000400000404000), CONST64(0x0000401000404000), CONST64(0x0000400040404000), CONST64(0x0000401040404000), + CONST64(0x0000400000000040), CONST64(0x0000401000000040), CONST64(0x0000400040000040), CONST64(0x0000401040000040), + CONST64(0x0000400000400040), CONST64(0x0000401000400040), CONST64(0x0000400040400040), CONST64(0x0000401040400040), + CONST64(0x0000400000004040), CONST64(0x0000401000004040), CONST64(0x0000400040004040), CONST64(0x0000401040004040), + CONST64(0x0000400000404040), CONST64(0x0000401000404040), CONST64(0x0000400040404040), CONST64(0x0000401040404040), + CONST64(0x4000400000000000), CONST64(0x4000401000000000), CONST64(0x4000400040000000), CONST64(0x4000401040000000), + CONST64(0x4000400000400000), CONST64(0x4000401000400000), CONST64(0x4000400040400000), CONST64(0x4000401040400000), + CONST64(0x4000400000004000), CONST64(0x4000401000004000), CONST64(0x4000400040004000), CONST64(0x4000401040004000), + CONST64(0x4000400000404000), CONST64(0x4000401000404000), CONST64(0x4000400040404000), CONST64(0x4000401040404000), + CONST64(0x4000400000000040), CONST64(0x4000401000000040), CONST64(0x4000400040000040), CONST64(0x4000401040000040), + CONST64(0x4000400000400040), CONST64(0x4000401000400040), CONST64(0x4000400040400040), CONST64(0x4000401040400040), + CONST64(0x4000400000004040), CONST64(0x4000401000004040), CONST64(0x4000400040004040), CONST64(0x4000401040004040), + CONST64(0x4000400000404040), CONST64(0x4000401000404040), CONST64(0x4000400040404040), CONST64(0x4000401040404040), + CONST64(0x0040400000000000), CONST64(0x0040401000000000), CONST64(0x0040400040000000), CONST64(0x0040401040000000), + CONST64(0x0040400000400000), CONST64(0x0040401000400000), CONST64(0x0040400040400000), CONST64(0x0040401040400000), + CONST64(0x0040400000004000), CONST64(0x0040401000004000), CONST64(0x0040400040004000), CONST64(0x0040401040004000), + CONST64(0x0040400000404000), CONST64(0x0040401000404000), CONST64(0x0040400040404000), CONST64(0x0040401040404000), + CONST64(0x0040400000000040), CONST64(0x0040401000000040), CONST64(0x0040400040000040), CONST64(0x0040401040000040), + CONST64(0x0040400000400040), CONST64(0x0040401000400040), CONST64(0x0040400040400040), CONST64(0x0040401040400040), + CONST64(0x0040400000004040), CONST64(0x0040401000004040), CONST64(0x0040400040004040), CONST64(0x0040401040004040), + CONST64(0x0040400000404040), CONST64(0x0040401000404040), CONST64(0x0040400040404040), CONST64(0x0040401040404040), + CONST64(0x4040400000000000), CONST64(0x4040401000000000), CONST64(0x4040400040000000), CONST64(0x4040401040000000), + CONST64(0x4040400000400000), CONST64(0x4040401000400000), CONST64(0x4040400040400000), CONST64(0x4040401040400000), + CONST64(0x4040400000004000), CONST64(0x4040401000004000), CONST64(0x4040400040004000), CONST64(0x4040401040004000), + CONST64(0x4040400000404000), CONST64(0x4040401000404000), CONST64(0x4040400040404000), CONST64(0x4040401040404000), + CONST64(0x4040400000000040), CONST64(0x4040401000000040), CONST64(0x4040400040000040), CONST64(0x4040401040000040), + CONST64(0x4040400000400040), CONST64(0x4040401000400040), CONST64(0x4040400040400040), CONST64(0x4040401040400040), + CONST64(0x4040400000004040), CONST64(0x4040401000004040), CONST64(0x4040400040004040), CONST64(0x4040401040004040), + CONST64(0x4040400000404040), CONST64(0x4040401000404040), CONST64(0x4040400040404040), CONST64(0x4040401040404040) + }}; + +#endif + + +static void cookey(const ulong32 *raw1, ulong32 *keyout); + +#ifdef LTC_CLEAN_STACK +static void _deskey(const unsigned char *key, short edf, ulong32 *keyout) +#else +static void deskey(const unsigned char *key, short edf, ulong32 *keyout) +#endif +{ + ulong32 i, j, l, m, n, kn[32]; + unsigned char pc1m[56], pcr[56]; + + for (j=0; j < 56; j++) { + l = (ulong32)pc1[j]; + m = l & 7; + pc1m[j] = (unsigned char)((key[l >> 3U] & bytebit[m]) == bytebit[m] ? 1 : 0); + } + + for (i=0; i < 16; i++) { + if (edf == DE1) { + m = (15 - i) << 1; + } else { + m = i << 1; + } + n = m + 1; + kn[m] = kn[n] = 0L; + for (j=0; j < 28; j++) { + l = j + (ulong32)totrot[i]; + if (l < 28) { + pcr[j] = pc1m[l]; + } else { + pcr[j] = pc1m[l - 28]; + } + } + for (/*j = 28*/; j < 56; j++) { + l = j + (ulong32)totrot[i]; + if (l < 56) { + pcr[j] = pc1m[l]; + } else { + pcr[j] = pc1m[l - 28]; + } + } + for (j=0; j < 24; j++) { + if ((int)pcr[(int)pc2[j]] != 0) { + kn[m] |= bigbyte[j]; + } + if ((int)pcr[(int)pc2[j+24]] != 0) { + kn[n] |= bigbyte[j]; + } + } + } + + cookey(kn, keyout); +} + +#ifdef LTC_CLEAN_STACK +static void deskey(const unsigned char *key, short edf, ulong32 *keyout) +{ + _deskey(key, edf, keyout); + burn_stack(sizeof(int)*5 + sizeof(ulong32)*32 + sizeof(unsigned char)*112); +} +#endif + +#ifdef LTC_CLEAN_STACK +static void _cookey(const ulong32 *raw1, ulong32 *keyout) +#else +static void cookey(const ulong32 *raw1, ulong32 *keyout) +#endif +{ + ulong32 *cook; + const ulong32 *raw0; + ulong32 dough[32]; + int i; + + cook = dough; + for(i=0; i < 16; i++, raw1++) + { + raw0 = raw1++; + *cook = (*raw0 & 0x00fc0000L) << 6; + *cook |= (*raw0 & 0x00000fc0L) << 10; + *cook |= (*raw1 & 0x00fc0000L) >> 10; + *cook++ |= (*raw1 & 0x00000fc0L) >> 6; + *cook = (*raw0 & 0x0003f000L) << 12; + *cook |= (*raw0 & 0x0000003fL) << 16; + *cook |= (*raw1 & 0x0003f000L) >> 4; + *cook++ |= (*raw1 & 0x0000003fL); + } + + XMEMCPY(keyout, dough, sizeof dough); +} + +#ifdef LTC_CLEAN_STACK +static void cookey(const ulong32 *raw1, ulong32 *keyout) +{ + _cookey(raw1, keyout); + burn_stack(sizeof(ulong32 *) * 2 + sizeof(ulong32)*32 + sizeof(int)); +} +#endif + +#ifndef LTC_CLEAN_STACK +static void desfunc(ulong32 *block, const ulong32 *keys) +#else +static void _desfunc(ulong32 *block, const ulong32 *keys) +#endif +{ + ulong32 work, right, leftt; + int cur_round; + + leftt = block[0]; + right = block[1]; + +#ifdef LTC_SMALL_CODE + work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL; + right ^= work; + leftt ^= (work << 4); + + work = ((leftt >> 16) ^ right) & 0x0000ffffL; + right ^= work; + leftt ^= (work << 16); + + work = ((right >> 2) ^ leftt) & 0x33333333L; + leftt ^= work; + right ^= (work << 2); + + work = ((right >> 8) ^ leftt) & 0x00ff00ffL; + leftt ^= work; + right ^= (work << 8); + + right = ROLc(right, 1); + work = (leftt ^ right) & 0xaaaaaaaaL; + + leftt ^= work; + right ^= work; + leftt = ROLc(leftt, 1); +#else + { + ulong64 tmp; + tmp = des_ip[0][byte(leftt, 0)] ^ + des_ip[1][byte(leftt, 1)] ^ + des_ip[2][byte(leftt, 2)] ^ + des_ip[3][byte(leftt, 3)] ^ + des_ip[4][byte(right, 0)] ^ + des_ip[5][byte(right, 1)] ^ + des_ip[6][byte(right, 2)] ^ + des_ip[7][byte(right, 3)]; + leftt = (ulong32)(tmp >> 32); + right = (ulong32)(tmp & 0xFFFFFFFFUL); + } +#endif + + for (cur_round = 0; cur_round < 8; cur_round++) { + work = RORc(right, 4) ^ *keys++; + leftt ^= SP7[work & 0x3fL] + ^ SP5[(work >> 8) & 0x3fL] + ^ SP3[(work >> 16) & 0x3fL] + ^ SP1[(work >> 24) & 0x3fL]; + work = right ^ *keys++; + leftt ^= SP8[ work & 0x3fL] + ^ SP6[(work >> 8) & 0x3fL] + ^ SP4[(work >> 16) & 0x3fL] + ^ SP2[(work >> 24) & 0x3fL]; + + work = RORc(leftt, 4) ^ *keys++; + right ^= SP7[ work & 0x3fL] + ^ SP5[(work >> 8) & 0x3fL] + ^ SP3[(work >> 16) & 0x3fL] + ^ SP1[(work >> 24) & 0x3fL]; + work = leftt ^ *keys++; + right ^= SP8[ work & 0x3fL] + ^ SP6[(work >> 8) & 0x3fL] + ^ SP4[(work >> 16) & 0x3fL] + ^ SP2[(work >> 24) & 0x3fL]; + } + +#ifdef LTC_SMALL_CODE + right = RORc(right, 1); + work = (leftt ^ right) & 0xaaaaaaaaL; + leftt ^= work; + right ^= work; + leftt = RORc(leftt, 1); + work = ((leftt >> 8) ^ right) & 0x00ff00ffL; + right ^= work; + leftt ^= (work << 8); + /* -- */ + work = ((leftt >> 2) ^ right) & 0x33333333L; + right ^= work; + leftt ^= (work << 2); + work = ((right >> 16) ^ leftt) & 0x0000ffffL; + leftt ^= work; + right ^= (work << 16); + work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL; + leftt ^= work; + right ^= (work << 4); +#else + { + ulong64 tmp; + tmp = des_fp[0][byte(leftt, 0)] ^ + des_fp[1][byte(leftt, 1)] ^ + des_fp[2][byte(leftt, 2)] ^ + des_fp[3][byte(leftt, 3)] ^ + des_fp[4][byte(right, 0)] ^ + des_fp[5][byte(right, 1)] ^ + des_fp[6][byte(right, 2)] ^ + des_fp[7][byte(right, 3)]; + leftt = (ulong32)(tmp >> 32); + right = (ulong32)(tmp & 0xFFFFFFFFUL); + } +#endif + + block[0] = right; + block[1] = leftt; +} + +#ifdef LTC_CLEAN_STACK +static void desfunc(ulong32 *block, const ulong32 *keys) +{ + _desfunc(block, keys); + burn_stack(sizeof(ulong32) * 4 + sizeof(int)); +} +#endif + + /** + Initialize the LTC_DES block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful + */ +int des_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if (num_rounds != 0 && num_rounds != 16) { + return CRYPT_INVALID_ROUNDS; + } + + if (keylen != 8) { + return CRYPT_INVALID_KEYSIZE; + } + + deskey(key, EN0, skey->des.ek); + deskey(key, DE1, skey->des.dk); + + return CRYPT_OK; +} + + /** + Initialize the 3LTC_DES-EDE block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful + */ +int des3_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if(num_rounds != 0 && num_rounds != 16) { + return CRYPT_INVALID_ROUNDS; + } + + if (keylen != 24) { + return CRYPT_INVALID_KEYSIZE; + } + + deskey(key, EN0, skey->des3.ek[0]); + deskey(key+8, DE1, skey->des3.ek[1]); + deskey(key+16, EN0, skey->des3.ek[2]); + + deskey(key, DE1, skey->des3.dk[2]); + deskey(key+8, EN0, skey->des3.dk[1]); + deskey(key+16, DE1, skey->des3.dk[0]); + + return CRYPT_OK; +} + +/** + Encrypts a block of text with LTC_DES + @param pt The input plaintext (8 bytes) + @param ct The output ciphertext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +int des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey) +{ + ulong32 work[2]; + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + LOAD32H(work[0], pt+0); + LOAD32H(work[1], pt+4); + desfunc(work, skey->des.ek); + STORE32H(work[0],ct+0); + STORE32H(work[1],ct+4); + return CRYPT_OK; +} + +/** + Decrypts a block of text with LTC_DES + @param ct The input ciphertext (8 bytes) + @param pt The output plaintext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +int des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) +{ + ulong32 work[2]; + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + LOAD32H(work[0], ct+0); + LOAD32H(work[1], ct+4); + desfunc(work, skey->des.dk); + STORE32H(work[0],pt+0); + STORE32H(work[1],pt+4); + return CRYPT_OK; +} + +/** + Encrypts a block of text with 3LTC_DES-EDE + @param pt The input plaintext (8 bytes) + @param ct The output ciphertext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +int des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey) +{ + ulong32 work[2]; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + LOAD32H(work[0], pt+0); + LOAD32H(work[1], pt+4); + desfunc(work, skey->des3.ek[0]); + desfunc(work, skey->des3.ek[1]); + desfunc(work, skey->des3.ek[2]); + STORE32H(work[0],ct+0); + STORE32H(work[1],ct+4); + return CRYPT_OK; +} + +/** + Decrypts a block of text with 3LTC_DES-EDE + @param ct The input ciphertext (8 bytes) + @param pt The output plaintext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +int des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) +{ + ulong32 work[2]; + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + LOAD32H(work[0], ct+0); + LOAD32H(work[1], ct+4); + desfunc(work, skey->des3.dk[0]); + desfunc(work, skey->des3.dk[1]); + desfunc(work, skey->des3.dk[2]); + STORE32H(work[0],pt+0); + STORE32H(work[1],pt+4); + return CRYPT_OK; +} + +/** + Performs a self-test of the LTC_DES block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int des_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + int err; + static const struct des_test_case { + int num, mode; /* mode 1 = encrypt */ + unsigned char key[8], txt[8], out[8]; + } cases[] = { + { 1, 1, { 0x10, 0x31, 0x6E, 0x02, 0x8C, 0x8F, 0x3B, 0x4A }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x82, 0xDC, 0xBA, 0xFB, 0xDE, 0xAB, 0x66, 0x02 } }, + { 2, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00 }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xDD, 0x7F, 0x12, 0x1C, 0xA5, 0x01, 0x56, 0x19 }, + { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 4, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x2E, 0x86, 0x53, 0x10, 0x4F, 0x38, 0x34, 0xEA }, + { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 5, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x4B, 0xD3, 0x88, 0xFF, 0x6C, 0xD8, 0x1D, 0x4F }, + { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 6, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x20, 0xB9, 0xE7, 0x67, 0xB2, 0xFB, 0x14, 0x56 }, + { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 7, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x55, 0x57, 0x93, 0x80, 0xD7, 0x71, 0x38, 0xEF }, + { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 8, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x6C, 0xC5, 0xDE, 0xFA, 0xAF, 0x04, 0x51, 0x2F }, + { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 9, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x0D, 0x9F, 0x27, 0x9B, 0xA5, 0xD8, 0x72, 0x60 }, + { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + {10, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xD9, 0x03, 0x1B, 0x02, 0x71, 0xBD, 0x5A, 0x0A }, + { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + + { 1, 0, { 0x10, 0x31, 0x6E, 0x02, 0x8C, 0x8F, 0x3B, 0x4A }, + { 0x82, 0xDC, 0xBA, 0xFB, 0xDE, 0xAB, 0x66, 0x02 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 2, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00 } }, + { 3, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xDD, 0x7F, 0x12, 0x1C, 0xA5, 0x01, 0x56, 0x19 } }, + { 4, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x2E, 0x86, 0x53, 0x10, 0x4F, 0x38, 0x34, 0xEA } }, + { 5, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x4B, 0xD3, 0x88, 0xFF, 0x6C, 0xD8, 0x1D, 0x4F } }, + { 6, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x20, 0xB9, 0xE7, 0x67, 0xB2, 0xFB, 0x14, 0x56 } }, + { 7, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x55, 0x57, 0x93, 0x80, 0xD7, 0x71, 0x38, 0xEF } }, + { 8, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x6C, 0xC5, 0xDE, 0xFA, 0xAF, 0x04, 0x51, 0x2F } }, + { 9, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x0D, 0x9F, 0x27, 0x9B, 0xA5, 0xD8, 0x72, 0x60 } }, + {10, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xD9, 0x03, 0x1B, 0x02, 0x71, 0xBD, 0x5A, 0x0A } } + + /*** more test cases you could add if you are not convinced (the above test cases aren't really too good): + + key plaintext ciphertext + 0000000000000000 0000000000000000 8CA64DE9C1B123A7 + FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 7359B2163E4EDC58 + 3000000000000000 1000000000000001 958E6E627A05557B + 1111111111111111 1111111111111111 F40379AB9E0EC533 + 0123456789ABCDEF 1111111111111111 17668DFC7292532D + 1111111111111111 0123456789ABCDEF 8A5AE1F81AB8F2DD + 0000000000000000 0000000000000000 8CA64DE9C1B123A7 + FEDCBA9876543210 0123456789ABCDEF ED39D950FA74BCC4 + 7CA110454A1A6E57 01A1D6D039776742 690F5B0D9A26939B + 0131D9619DC1376E 5CD54CA83DEF57DA 7A389D10354BD271 + 07A1133E4A0B2686 0248D43806F67172 868EBB51CAB4599A + 3849674C2602319E 51454B582DDF440A 7178876E01F19B2A + 04B915BA43FEB5B6 42FD443059577FA2 AF37FB421F8C4095 + 0113B970FD34F2CE 059B5E0851CF143A 86A560F10EC6D85B + 0170F175468FB5E6 0756D8E0774761D2 0CD3DA020021DC09 + 43297FAD38E373FE 762514B829BF486A EA676B2CB7DB2B7A + 07A7137045DA2A16 3BDD119049372802 DFD64A815CAF1A0F + 04689104C2FD3B2F 26955F6835AF609A 5C513C9C4886C088 + 37D06BB516CB7546 164D5E404F275232 0A2AEEAE3FF4AB77 + 1F08260D1AC2465E 6B056E18759F5CCA EF1BF03E5DFA575A + 584023641ABA6176 004BD6EF09176062 88BF0DB6D70DEE56 + 025816164629B007 480D39006EE762F2 A1F9915541020B56 + 49793EBC79B3258F 437540C8698F3CFA 6FBF1CAFCFFD0556 + 4FB05E1515AB73A7 072D43A077075292 2F22E49BAB7CA1AC + 49E95D6D4CA229BF 02FE55778117F12A 5A6B612CC26CCE4A + 018310DC409B26D6 1D9D5C5018F728C2 5F4C038ED12B2E41 + 1C587F1C13924FEF 305532286D6F295A 63FAC0D034D9F793 + 0101010101010101 0123456789ABCDEF 617B3A0CE8F07100 + 1F1F1F1F0E0E0E0E 0123456789ABCDEF DB958605F8C8C606 + E0FEE0FEF1FEF1FE 0123456789ABCDEF EDBFD1C66C29CCC7 + 0000000000000000 FFFFFFFFFFFFFFFF 355550B2150E2451 + FFFFFFFFFFFFFFFF 0000000000000000 CAAAAF4DEAF1DBAE + 0123456789ABCDEF 0000000000000000 D5D44FF720683D0D + FEDCBA9876543210 FFFFFFFFFFFFFFFF 2A2BB008DF97C2F2 + + http://www.ecs.soton.ac.uk/~prw99r/ez438/vectors.txt + ***/ + }; + int i, y; + unsigned char tmp[8]; + symmetric_key des; + + for(i=0; i < (int)(sizeof(cases)/sizeof(cases[0])); i++) + { + if ((err = des_setup(cases[i].key, 8, 0, &des)) != CRYPT_OK) { + return err; + } + if (cases[i].mode != 0) { + des_ecb_encrypt(cases[i].txt, tmp, &des); + } else { + des_ecb_decrypt(cases[i].txt, tmp, &des); + } + + if (XMEMCMP(cases[i].out, tmp, sizeof(tmp)) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ + for (y = 0; y < 8; y++) tmp[y] = 0; + for (y = 0; y < 1000; y++) des_ecb_encrypt(tmp, tmp, &des); + for (y = 0; y < 1000; y++) des_ecb_decrypt(tmp, tmp, &des); + for (y = 0; y < 8; y++) if (tmp[y] != 0) return CRYPT_FAIL_TESTVECTOR; +} + + return CRYPT_OK; + #endif +} + +int des3_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + unsigned char key[24], pt[8], ct[8], tmp[8]; + symmetric_key skey; + int x, err; + + if ((err = des_test()) != CRYPT_OK) { + return err; + } + + for (x = 0; x < 8; x++) { + pt[x] = x; + } + + for (x = 0; x < 24; x++) { + key[x] = x; + } + + if ((err = des3_setup(key, 24, 0, &skey)) != CRYPT_OK) { + return err; + } + + des3_ecb_encrypt(pt, ct, &skey); + des3_ecb_decrypt(ct, tmp, &skey); + + if (XMEMCMP(pt, tmp, 8) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; + #endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void des_done(symmetric_key *skey) +{ +} + +/** Terminate the context + @param skey The scheduled key +*/ +void des3_done(symmetric_key *skey) +{ +} + + +/** + Gets suitable key size + @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. + @return CRYPT_OK if the input key size is acceptable. +*/ +int des_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if(*keysize < 8) { + return CRYPT_INVALID_KEYSIZE; + } + *keysize = 8; + return CRYPT_OK; +} + +/** + Gets suitable key size + @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. + @return CRYPT_OK if the input key size is acceptable. +*/ +int des3_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if(*keysize < 24) { + return CRYPT_INVALID_KEYSIZE; + } + *keysize = 24; + return CRYPT_OK; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/ciphers/des.c,v $ */ +/* $Revision: 1.15 $ */ +/* $Date: 2007/05/12 14:20:27 $ */ diff --git a/core/lib/libtomcrypt/src/ciphers/sub.mk b/core/lib/libtomcrypt/src/ciphers/sub.mk new file mode 100644 index 00000000000..17d65643f80 --- /dev/null +++ b/core/lib/libtomcrypt/src/ciphers/sub.mk @@ -0,0 +1,5 @@ +cflags-y += -Wno-unused-parameter + +srcs-y += aes.c +srcs-y += aes_tab.c +srcs-y += des.c diff --git a/core/lib/libtomcrypt/src/encauth/ccm/ccm_memory.c b/core/lib/libtomcrypt/src/encauth/ccm/ccm_memory.c new file mode 100644 index 00000000000..ba9be1f1204 --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/ccm/ccm_memory.c @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file ccm_memory.c + CCM support, process a block of memory, Tom St Denis +*/ + +#ifdef LTC_CCM_MODE + +/** + CCM encrypt/decrypt and produce an authentication tag + @param cipher The index of the cipher desired + @param key The secret key to use + @param keylen The length of the secret key (octets) + @param uskey A previously scheduled key [optional can be NULL] + @param nonce The session nonce [use once] + @param noncelen The length of the nonce + @param header The header for the session + @param headerlen The length of the header (octets) + @param pt [out] The plaintext + @param ptlen The length of the plaintext (octets) + @param ct [out] The ciphertext + @param tag [out] The destination tag + @param taglen [in/out] The max size and resulting size of the authentication tag + @param direction Encrypt or Decrypt direction (0 or 1) + @return CRYPT_OK if successful +*/ +int ccm_memory(int cipher, + const unsigned char *key, unsigned long keylen, + symmetric_key *uskey, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen, + int direction) +{ + unsigned char PAD[16], ctr[16], CTRPAD[16], b; + symmetric_key *skey; + int err; + unsigned long len, L, x, y, z, CTRlen; + + if (uskey == NULL) { + LTC_ARGCHK(key != NULL); + } + LTC_ARGCHK(nonce != NULL); + if (headerlen > 0) { + LTC_ARGCHK(header != NULL); + } + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(tag != NULL); + LTC_ARGCHK(taglen != NULL); + +#ifdef LTC_FAST + if (16 % sizeof(LTC_FAST_TYPE)) { + return CRYPT_INVALID_ARG; + } +#endif + + /* check cipher input */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + if (cipher_descriptor[cipher].block_length != 16) { + return CRYPT_INVALID_CIPHER; + } + + /* make sure the taglen is even and <= 16 */ + *taglen &= ~1; + if (*taglen > 16) { + *taglen = 16; + } + + /* can't use < 4 */ + if (*taglen < 4) { + return CRYPT_INVALID_ARG; + } + + /* is there an accelerator? */ + if (cipher_descriptor[cipher].accel_ccm_memory != NULL) { + return cipher_descriptor[cipher].accel_ccm_memory( + key, keylen, + uskey, + nonce, noncelen, + header, headerlen, + pt, ptlen, + ct, + tag, taglen, + direction); + } + + /* let's get the L value */ + len = ptlen; + L = 0; + while (len) { + ++L; + len >>= 8; + } + if (L <= 1) { + L = 2; + } + + /* increase L to match the nonce len */ + noncelen = (noncelen > 13) ? 13 : noncelen; + if ((15 - noncelen) > L) { + L = 15 - noncelen; + } + + /* decrease noncelen to match L */ + if ((noncelen + L) > 15) { + noncelen = 15 - L; + } + + /* allocate mem for the symmetric key */ + if (uskey == NULL) { + skey = XMALLOC(sizeof(*skey)); + if (skey == NULL) { + return CRYPT_MEM; + } + + /* initialize the cipher */ + if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, skey)) != CRYPT_OK) { + XFREE(skey); + return err; + } + } else { + skey = uskey; + } + + /* form B_0 == flags | Nonce N | l(m) */ + x = 0; + PAD[x++] = (unsigned char)(((headerlen > 0) ? (1<<6) : 0) | + (((*taglen - 2)>>1)<<3) | + (L-1)); + + /* nonce */ + for (y = 0; y < (16 - (L + 1)); y++) { + PAD[x++] = nonce[y]; + } + + /* store len */ + len = ptlen; + + /* shift len so the upper bytes of len are the contents of the length */ + for (y = L; y < 4; y++) { + len <<= 8; + } + + /* store l(m) (only store 32-bits) */ + for (y = 0; L > 4 && (L-y)>4; y++) { + PAD[x++] = 0; + } + for (; y < L; y++) { + PAD[x++] = (unsigned char)((len >> 24) & 255); + len <<= 8; + } + + /* encrypt PAD */ + if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { + goto error; + } + + /* handle header */ + if (headerlen > 0) { + x = 0; + + /* store length */ + if (headerlen < ((1UL<<16) - (1UL<<8))) { + PAD[x++] ^= (headerlen>>8) & 255; + PAD[x++] ^= headerlen & 255; + } else { + PAD[x++] ^= 0xFF; + PAD[x++] ^= 0xFE; + PAD[x++] ^= (headerlen>>24) & 255; + PAD[x++] ^= (headerlen>>16) & 255; + PAD[x++] ^= (headerlen>>8) & 255; + PAD[x++] ^= headerlen & 255; + } + + /* now add the data */ + for (y = 0; y < headerlen; y++) { + if (x == 16) { + /* full block so let's encrypt it */ + if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { + goto error; + } + x = 0; + } + PAD[x++] ^= header[y]; + } + + /* remainder? */ + if (x != 0) { + if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { + goto error; + } + } + } + + /* setup the ctr counter */ + x = 0; + + /* flags */ + ctr[x++] = (unsigned char)L-1; + + /* nonce */ + for (y = 0; y < (16 - (L+1)); ++y) { + ctr[x++] = nonce[y]; + } + /* offset */ + while (x < 16) { + ctr[x++] = 0; + } + + x = 0; + CTRlen = 16; + + /* now handle the PT */ + if (ptlen > 0) { + y = 0; +#ifdef LTC_FAST + if (ptlen & ~15) { + if (direction == CCM_ENCRYPT) { + for (; y < (ptlen & ~15); y += 16) { + /* increment the ctr? */ + for (z = 15; z > 15-L; z--) { + ctr[z] = (ctr[z] + 1) & 255; + if (ctr[z]) break; + } + if ((err = cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) { + goto error; + } + + /* xor the PT against the pad first */ + for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE*)(&PAD[z])) ^= *((LTC_FAST_TYPE*)(&pt[y+z])); + *((LTC_FAST_TYPE*)(&ct[y+z])) = *((LTC_FAST_TYPE*)(&pt[y+z])) ^ *((LTC_FAST_TYPE*)(&CTRPAD[z])); + } + if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { + goto error; + } + } + } else { + for (; y < (ptlen & ~15); y += 16) { + /* increment the ctr? */ + for (z = 15; z > 15-L; z--) { + ctr[z] = (ctr[z] + 1) & 255; + if (ctr[z]) break; + } + if ((err = cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) { + goto error; + } + + /* xor the PT against the pad last */ + for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE*)(&pt[y+z])) = *((LTC_FAST_TYPE*)(&ct[y+z])) ^ *((LTC_FAST_TYPE*)(&CTRPAD[z])); + *((LTC_FAST_TYPE*)(&PAD[z])) ^= *((LTC_FAST_TYPE*)(&pt[y+z])); + } + if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { + goto error; + } + } + } + } +#endif + + for (; y < ptlen; y++) { + /* increment the ctr? */ + if (CTRlen == 16) { + for (z = 15; z > 15-L; z--) { + ctr[z] = (ctr[z] + 1) & 255; + if (ctr[z]) break; + } + if ((err = cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) { + goto error; + } + CTRlen = 0; + } + + /* if we encrypt we add the bytes to the MAC first */ + if (direction == CCM_ENCRYPT) { + b = pt[y]; + ct[y] = b ^ CTRPAD[CTRlen++]; + } else { + b = ct[y] ^ CTRPAD[CTRlen++]; + pt[y] = b; + } + + if (x == 16) { + if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { + goto error; + } + x = 0; + } + PAD[x++] ^= b; + } + + if (x != 0) { + if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { + goto error; + } + } + } + + /* setup CTR for the TAG (zero the count) */ + for (y = 15; y > 15 - L; y--) { + ctr[y] = 0x00; + } + if ((err = cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) { + goto error; + } + + if (skey != uskey) { + cipher_descriptor[cipher].done(skey); + } + + /* store the TAG */ + for (x = 0; x < 16 && x < *taglen; x++) { + tag[x] = PAD[x] ^ CTRPAD[x]; + } + *taglen = x; + +#ifdef LTC_CLEAN_STACK + zeromem(skey, sizeof(*skey)); + zeromem(PAD, sizeof(PAD)); + zeromem(CTRPAD, sizeof(CTRPAD)); +#endif +error: + if (skey != uskey) { + XFREE(skey); + } + + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/ccm/ccm_memory.c,v $ */ +/* $Revision: 1.20 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/ccm/ccm_test.c b/core/lib/libtomcrypt/src/encauth/ccm/ccm_test.c new file mode 100644 index 00000000000..d0be92c1a15 --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/ccm/ccm_test.c @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file ccm_test.c + CCM support, process a block of memory, Tom St Denis +*/ + +#ifdef LTC_CCM_MODE + +int ccm_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + unsigned char key[16]; + unsigned char nonce[16]; + int noncelen; + unsigned char header[64]; + int headerlen; + unsigned char pt[64]; + int ptlen; + unsigned char ct[64]; + unsigned char tag[16]; + int taglen; + } tests[] = { + +/* 13 byte nonce, 8 byte auth, 23 byte pt */ +{ + { 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF }, + { 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xA0, + 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 }, + 13, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }, + 8, + { 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E }, + 23, + { 0x58, 0x8C, 0x97, 0x9A, 0x61, 0xC6, 0x63, 0xD2, + 0xF0, 0x66, 0xD0, 0xC2, 0xC0, 0xF9, 0x89, 0x80, + 0x6D, 0x5F, 0x6B, 0x61, 0xDA, 0xC3, 0x84 }, + { 0x17, 0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0 }, + 8 +}, + +/* 13 byte nonce, 12 byte header, 19 byte pt */ +{ + { 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF }, + { 0x00, 0x00, 0x00, 0x06, 0x05, 0x04, 0x03, 0xA0, + 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 }, + 13, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B }, + 12, + { 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E }, + 19, + { 0xA2, 0x8C, 0x68, 0x65, 0x93, 0x9A, 0x9A, 0x79, + 0xFA, 0xAA, 0x5C, 0x4C, 0x2A, 0x9D, 0x4A, 0x91, + 0xCD, 0xAC, 0x8C }, + { 0x96, 0xC8, 0x61, 0xB9, 0xC9, 0xE6, 0x1E, 0xF1 }, + 8 +}, + +/* supplied by Brian Gladman */ +{ + { 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f }, + { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 }, + 7, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }, + 8, + { 0x20, 0x21, 0x22, 0x23 }, + 4, + { 0x71, 0x62, 0x01, 0x5b }, + { 0x4d, 0xac, 0x25, 0x5d }, + 4 +}, + +{ + { 0xc9, 0x7c, 0x1f, 0x67, 0xce, 0x37, 0x11, 0x85, + 0x51, 0x4a, 0x8a, 0x19, 0xf2, 0xbd, 0xd5, 0x2f }, + { 0x00, 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08, 0xb5, + 0x03, 0x97, 0x76, 0xe7, 0x0c }, + 13, + { 0x08, 0x40, 0x0f, 0xd2, 0xe1, 0x28, 0xa5, 0x7c, + 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08, 0xab, 0xae, + 0xa5, 0xb8, 0xfc, 0xba, 0x00, 0x00 }, + 22, + { 0xf8, 0xba, 0x1a, 0x55, 0xd0, 0x2f, 0x85, 0xae, + 0x96, 0x7b, 0xb6, 0x2f, 0xb6, 0xcd, 0xa8, 0xeb, + 0x7e, 0x78, 0xa0, 0x50 }, + 20, + { 0xf3, 0xd0, 0xa2, 0xfe, 0x9a, 0x3d, 0xbf, 0x23, + 0x42, 0xa6, 0x43, 0xe4, 0x32, 0x46, 0xe8, 0x0c, + 0x3c, 0x04, 0xd0, 0x19 }, + { 0x78, 0x45, 0xce, 0x0b, 0x16, 0xf9, 0x76, 0x23 }, + 8 +}, + +}; + unsigned long taglen, x; + unsigned char buf[64], buf2[64], tag2[16], tag[16]; + int err, idx; + symmetric_key skey; + + idx = find_cipher("aes"); + if (idx == -1) { + idx = find_cipher("rijndael"); + if (idx == -1) { + return CRYPT_NOP; + } + } + + for (x = 0; x < (sizeof(tests)/sizeof(tests[0])); x++) { + taglen = tests[x].taglen; + if ((err = cipher_descriptor[idx].setup(tests[x].key, 16, 0, &skey)) != CRYPT_OK) { + return err; + } + + if ((err = ccm_memory(idx, + tests[x].key, 16, + &skey, + tests[x].nonce, tests[x].noncelen, + tests[x].header, tests[x].headerlen, + (unsigned char*)tests[x].pt, tests[x].ptlen, + buf, + tag, &taglen, 0)) != CRYPT_OK) { + return err; + } + + if (XMEMCMP(buf, tests[x].ct, tests[x].ptlen)) { + return CRYPT_FAIL_TESTVECTOR; + } + if (XMEMCMP(tag, tests[x].tag, tests[x].taglen)) { + return CRYPT_FAIL_TESTVECTOR; + } + + if ((err = ccm_memory(idx, + tests[x].key, 16, + NULL, + tests[x].nonce, tests[x].noncelen, + tests[x].header, tests[x].headerlen, + buf2, tests[x].ptlen, + buf, + tag2, &taglen, 1 )) != CRYPT_OK) { + return err; + } + + if (XMEMCMP(buf2, tests[x].pt, tests[x].ptlen)) { + return CRYPT_FAIL_TESTVECTOR; + } + if (XMEMCMP(tag2, tests[x].tag, tests[x].taglen)) { + return CRYPT_FAIL_TESTVECTOR; + } + cipher_descriptor[idx].done(&skey); + } + return CRYPT_OK; +#endif +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/ccm/ccm_test.c,v $ */ +/* $Revision: 1.10 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/ccm/sub.mk b/core/lib/libtomcrypt/src/encauth/ccm/sub.mk new file mode 100644 index 00000000000..3dc83808de7 --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/ccm/sub.mk @@ -0,0 +1,2 @@ +srcs-y += ccm_memory.c +srcs-y += ccm_test.c diff --git a/core/lib/libtomcrypt/src/encauth/eax/eax_addheader.c b/core/lib/libtomcrypt/src/encauth/eax/eax_addheader.c new file mode 100644 index 00000000000..0e688442632 --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/eax/eax_addheader.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +/** + @file eax_addheader.c + EAX implementation, add meta-data, by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_EAX_MODE + +/** + add header (metadata) to the stream + @param eax The current EAX state + @param header The header (meta-data) data you wish to add to the state + @param length The length of the header data + @return CRYPT_OK if successful +*/ +int eax_addheader(eax_state *eax, const unsigned char *header, + unsigned long length) +{ + LTC_ARGCHK(eax != NULL); + LTC_ARGCHK(header != NULL); + return omac_process(&eax->headeromac, header, length); +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/eax/eax_addheader.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/eax/eax_decrypt.c b/core/lib/libtomcrypt/src/encauth/eax/eax_decrypt.c new file mode 100644 index 00000000000..ffe0d255794 --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/eax/eax_decrypt.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file eax_decrypt.c + EAX implementation, decrypt block, by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_EAX_MODE + +/** + Decrypt data with the EAX protocol + @param eax The EAX state + @param ct The ciphertext + @param pt [out] The plaintext + @param length The length (octets) of the ciphertext + @return CRYPT_OK if successful +*/ +int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, + unsigned long length) +{ + int err; + + LTC_ARGCHK(eax != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + + /* omac ciphertext */ + if ((err = omac_process(&eax->ctomac, ct, length)) != CRYPT_OK) { + return err; + } + + /* decrypt */ + return ctr_decrypt(ct, pt, length, &eax->ctr); +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/eax/eax_decrypt.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/eax/eax_decrypt_verify_memory.c b/core/lib/libtomcrypt/src/encauth/eax/eax_decrypt_verify_memory.c new file mode 100644 index 00000000000..30a81c8de75 --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/eax/eax_decrypt_verify_memory.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file eax_decrypt_verify_memory.c + EAX implementation, decrypt block of memory, by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_EAX_MODE + +/** + Decrypt a block of memory and verify the provided MAC tag with EAX + @param cipher The index of the cipher desired + @param key The secret key + @param keylen The length of the key (octets) + @param nonce The nonce data (use once) for the session + @param noncelen The length of the nonce data. + @param header The session header data + @param headerlen The length of the header (octets) + @param ct The ciphertext + @param ctlen The length of the ciphertext (octets) + @param pt [out] The plaintext + @param tag The authentication tag provided by the encoder + @param taglen [in/out] The length of the tag (octets) + @param stat [out] The result of the decryption (1==valid tag, 0==invalid) + @return CRYPT_OK if successful regardless of the resulting tag comparison +*/ +int eax_decrypt_verify_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + unsigned char *tag, unsigned long taglen, + int *stat) +{ + int err; + eax_state *eax; + unsigned char *buf; + unsigned long buflen; + + LTC_ARGCHK(stat != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(tag != NULL); + + /* default to zero */ + *stat = 0; + + /* allocate ram */ + buf = XMALLOC(taglen); + eax = XMALLOC(sizeof(*eax)); + if (eax == NULL || buf == NULL) { + if (eax != NULL) { + XFREE(eax); + } + if (buf != NULL) { + XFREE(buf); + } + return CRYPT_MEM; + } + + if ((err = eax_init(eax, cipher, key, keylen, nonce, noncelen, header, headerlen)) != CRYPT_OK) { + goto LBL_ERR; + } + + if ((err = eax_decrypt(eax, ct, pt, ctlen)) != CRYPT_OK) { + goto LBL_ERR; + } + + buflen = taglen; + if ((err = eax_done(eax, buf, &buflen)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* compare tags */ + if (buflen >= taglen && XMEMCMP(buf, tag, taglen) == 0) { + *stat = 1; + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(buf, taglen); + zeromem(eax, sizeof(*eax)); +#endif + + XFREE(eax); + XFREE(buf); + + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/eax/eax_decrypt_verify_memory.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/eax/eax_done.c b/core/lib/libtomcrypt/src/encauth/eax/eax_done.c new file mode 100644 index 00000000000..63297b0919e --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/eax/eax_done.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file eax_done.c + EAX implementation, terminate session, by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_EAX_MODE + +/** + Terminate an EAX session and get the tag. + @param eax The EAX state + @param tag [out] The destination of the authentication tag + @param taglen [in/out] The max length and resulting length of the authentication tag + @return CRYPT_OK if successful +*/ +int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen) +{ + int err; + unsigned char *headermac, *ctmac; + unsigned long x, len; + + LTC_ARGCHK(eax != NULL); + LTC_ARGCHK(tag != NULL); + LTC_ARGCHK(taglen != NULL); + + /* allocate ram */ + headermac = XMALLOC(MAXBLOCKSIZE); + ctmac = XMALLOC(MAXBLOCKSIZE); + + if (headermac == NULL || ctmac == NULL) { + if (headermac != NULL) { + XFREE(headermac); + } + if (ctmac != NULL) { + XFREE(ctmac); + } + return CRYPT_MEM; + } + + /* finish ctomac */ + len = MAXBLOCKSIZE; + if ((err = omac_done(&eax->ctomac, ctmac, &len)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* finish headeromac */ + + /* note we specifically don't reset len so the two lens are minimal */ + + if ((err = omac_done(&eax->headeromac, headermac, &len)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* terminate the CTR chain */ + if ((err = ctr_done(&eax->ctr)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* compute N xor H xor C */ + for (x = 0; x < len && x < *taglen; x++) { + tag[x] = eax->N[x] ^ headermac[x] ^ ctmac[x]; + } + *taglen = x; + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(ctmac, MAXBLOCKSIZE); + zeromem(headermac, MAXBLOCKSIZE); + zeromem(eax, sizeof(*eax)); +#endif + + XFREE(ctmac); + XFREE(headermac); + + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/eax/eax_done.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/eax/eax_encrypt.c b/core/lib/libtomcrypt/src/encauth/eax/eax_encrypt.c new file mode 100644 index 00000000000..07572dca6b0 --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/eax/eax_encrypt.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file eax_encrypt.c + EAX implementation, encrypt block by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_EAX_MODE + +/** + Encrypt with EAX a block of data. + @param eax The EAX state + @param pt The plaintext to encrypt + @param ct [out] The ciphertext as encrypted + @param length The length of the plaintext (octets) + @return CRYPT_OK if successful +*/ +int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, + unsigned long length) +{ + int err; + + LTC_ARGCHK(eax != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + + /* encrypt */ + if ((err = ctr_encrypt(pt, ct, length, &eax->ctr)) != CRYPT_OK) { + return err; + } + + /* omac ciphertext */ + return omac_process(&eax->ctomac, ct, length); +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/eax/eax_encrypt.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/eax/eax_encrypt_authenticate_memory.c b/core/lib/libtomcrypt/src/encauth/eax/eax_encrypt_authenticate_memory.c new file mode 100644 index 00000000000..5b40386c274 --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/eax/eax_encrypt_authenticate_memory.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file eax_encrypt_authenticate_memory.c + EAX implementation, encrypt a block of memory, by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_EAX_MODE + +/** + EAX encrypt and produce an authentication tag + @param cipher The index of the cipher desired + @param key The secret key to use + @param keylen The length of the secret key (octets) + @param nonce The session nonce [use once] + @param noncelen The length of the nonce + @param header The header for the session + @param headerlen The length of the header (octets) + @param pt The plaintext + @param ptlen The length of the plaintext (octets) + @param ct [out] The ciphertext + @param tag [out] The destination tag + @param taglen [in/out] The max size and resulting size of the authentication tag + @return CRYPT_OK if successful +*/ +int eax_encrypt_authenticate_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen, + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen) +{ + int err; + eax_state *eax; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(tag != NULL); + LTC_ARGCHK(taglen != NULL); + + eax = XMALLOC(sizeof(*eax)); + + if ((err = eax_init(eax, cipher, key, keylen, nonce, noncelen, header, headerlen)) != CRYPT_OK) { + goto LBL_ERR; + } + + if ((err = eax_encrypt(eax, pt, ct, ptlen)) != CRYPT_OK) { + goto LBL_ERR; + } + + if ((err = eax_done(eax, tag, taglen)) != CRYPT_OK) { + goto LBL_ERR; + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(eax, sizeof(*eax)); +#endif + + XFREE(eax); + + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/eax/eax_encrypt_authenticate_memory.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/eax/eax_init.c b/core/lib/libtomcrypt/src/encauth/eax/eax_init.c new file mode 100644 index 00000000000..1ae30d9d54a --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/eax/eax_init.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file eax_init.c + EAX implementation, initialized EAX state, by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_EAX_MODE + +/** + Initialized an EAX state + @param eax [out] The EAX state to initialize + @param cipher The index of the desired cipher + @param key The secret key + @param keylen The length of the secret key (octets) + @param nonce The use-once nonce for the session + @param noncelen The length of the nonce (octets) + @param header The header for the EAX state + @param headerlen The header length (octets) + @return CRYPT_OK if successful +*/ +int eax_init(eax_state *eax, int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen) +{ + unsigned char *buf; + int err, blklen; + omac_state *omac; + unsigned long len; + + + LTC_ARGCHK(eax != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(nonce != NULL); + if (headerlen > 0) { + LTC_ARGCHK(header != NULL); + } + + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + blklen = cipher_descriptor[cipher].block_length; + + /* allocate ram */ + buf = XMALLOC(MAXBLOCKSIZE); + omac = XMALLOC(sizeof(*omac)); + + if (buf == NULL || omac == NULL) { + if (buf != NULL) { + XFREE(buf); + } + if (omac != NULL) { + XFREE(omac); + } + return CRYPT_MEM; + } + + /* N = LTC_OMAC_0K(nonce) */ + zeromem(buf, MAXBLOCKSIZE); + if ((err = omac_init(omac, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* omac the [0]_n */ + if ((err = omac_process(omac, buf, blklen)) != CRYPT_OK) { + goto LBL_ERR; + } + /* omac the nonce */ + if ((err = omac_process(omac, nonce, noncelen)) != CRYPT_OK) { + goto LBL_ERR; + } + /* store result */ + len = sizeof(eax->N); + if ((err = omac_done(omac, eax->N, &len)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* H = LTC_OMAC_1K(header) */ + zeromem(buf, MAXBLOCKSIZE); + buf[blklen - 1] = 1; + + if ((err = omac_init(&eax->headeromac, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* omac the [1]_n */ + if ((err = omac_process(&eax->headeromac, buf, blklen)) != CRYPT_OK) { + goto LBL_ERR; + } + /* omac the header */ + if (headerlen != 0) { + if ((err = omac_process(&eax->headeromac, header, headerlen)) != CRYPT_OK) { + goto LBL_ERR; + } + } + + /* note we don't finish the headeromac, this allows us to add more header later */ + + /* setup the CTR mode */ + if ((err = ctr_start(cipher, eax->N, key, keylen, 0, CTR_COUNTER_BIG_ENDIAN, &eax->ctr)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* setup the LTC_OMAC for the ciphertext */ + if ((err = omac_init(&eax->ctomac, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* omac [2]_n */ + zeromem(buf, MAXBLOCKSIZE); + buf[blklen-1] = 2; + if ((err = omac_process(&eax->ctomac, buf, blklen)) != CRYPT_OK) { + goto LBL_ERR; + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(buf, MAXBLOCKSIZE); + zeromem(omac, sizeof(*omac)); +#endif + + XFREE(omac); + XFREE(buf); + + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/eax/eax_init.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/eax/eax_test.c b/core/lib/libtomcrypt/src/encauth/eax/eax_test.c new file mode 100644 index 00000000000..0d70b7fe8c9 --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/eax/eax_test.c @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file eax_test.c + EAX implementation, self-test, by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_EAX_MODE + +/** + Test the EAX implementation + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled +*/ +int eax_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + int keylen, + noncelen, + headerlen, + msglen; + + unsigned char key[MAXBLOCKSIZE], + nonce[MAXBLOCKSIZE], + header[MAXBLOCKSIZE], + plaintext[MAXBLOCKSIZE], + ciphertext[MAXBLOCKSIZE], + tag[MAXBLOCKSIZE]; + } tests[] = { + +/* NULL message */ +{ + 16, 0, 0, 0, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0 }, + /* header */ + { 0 }, + /* plaintext */ + { 0 }, + /* ciphertext */ + { 0 }, + /* tag */ + { 0x9a, 0xd0, 0x7e, 0x7d, 0xbf, 0xf3, 0x01, 0xf5, + 0x05, 0xde, 0x59, 0x6b, 0x96, 0x15, 0xdf, 0xff } +}, + +/* test with nonce */ +{ + 16, 16, 0, 0, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* header */ + { 0 }, + /* plaintext */ + { 0 }, + /* ciphertext */ + { 0 }, + /* tag */ + { 0x1c, 0xe1, 0x0d, 0x3e, 0xff, 0xd4, 0xca, 0xdb, + 0xe2, 0xe4, 0x4b, 0x58, 0xd6, 0x0a, 0xb9, 0xec } +}, + +/* test with header [no nonce] */ +{ + 16, 0, 16, 0, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0 }, + /* header */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* plaintext */ + { 0 }, + /* ciphertext */ + { 0 }, + /* tag */ + { 0x3a, 0x69, 0x8f, 0x7a, 0x27, 0x0e, 0x51, 0xb0, + 0xf6, 0x5b, 0x3d, 0x3e, 0x47, 0x19, 0x3c, 0xff } +}, + +/* test with header + nonce + plaintext */ +{ + 16, 16, 16, 32, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* header */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* plaintext */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, + /* ciphertext */ + { 0x29, 0xd8, 0x78, 0xd1, 0xa3, 0xbe, 0x85, 0x7b, + 0x6f, 0xb8, 0xc8, 0xea, 0x59, 0x50, 0xa7, 0x78, + 0x33, 0x1f, 0xbf, 0x2c, 0xcf, 0x33, 0x98, 0x6f, + 0x35, 0xe8, 0xcf, 0x12, 0x1d, 0xcb, 0x30, 0xbc }, + /* tag */ + { 0x4f, 0xbe, 0x03, 0x38, 0xbe, 0x1c, 0x8c, 0x7e, + 0x1d, 0x7a, 0xe7, 0xe4, 0x5b, 0x92, 0xc5, 0x87 } +}, + +/* test with header + nonce + plaintext [not even sizes!] */ +{ + 16, 15, 14, 29, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e }, + /* header */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d }, + /* plaintext */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c }, + /* ciphertext */ + { 0xdd, 0x25, 0xc7, 0x54, 0xc5, 0xb1, 0x7c, 0x59, + 0x28, 0xb6, 0x9b, 0x73, 0x15, 0x5f, 0x7b, 0xb8, + 0x88, 0x8f, 0xaf, 0x37, 0x09, 0x1a, 0xd9, 0x2c, + 0x8a, 0x24, 0xdb, 0x86, 0x8b }, + /* tag */ + { 0x0d, 0x1a, 0x14, 0xe5, 0x22, 0x24, 0xff, 0xd2, + 0x3a, 0x05, 0xfa, 0x02, 0xcd, 0xef, 0x52, 0xda } +}, + +/* Vectors from Brian Gladman */ + +{ + 16, 16, 8, 0, + /* key */ + { 0x23, 0x39, 0x52, 0xde, 0xe4, 0xd5, 0xed, 0x5f, + 0x9b, 0x9c, 0x6d, 0x6f, 0xf8, 0x0f, 0xf4, 0x78 }, + /* nonce */ + { 0x62, 0xec, 0x67, 0xf9, 0xc3, 0xa4, 0xa4, 0x07, + 0xfc, 0xb2, 0xa8, 0xc4, 0x90, 0x31, 0xa8, 0xb3 }, + /* header */ + { 0x6b, 0xfb, 0x91, 0x4f, 0xd0, 0x7e, 0xae, 0x6b }, + /* PT */ + { 0x00 }, + /* CT */ + { 0x00 }, + /* tag */ + { 0xe0, 0x37, 0x83, 0x0e, 0x83, 0x89, 0xf2, 0x7b, + 0x02, 0x5a, 0x2d, 0x65, 0x27, 0xe7, 0x9d, 0x01 } +}, + +{ + 16, 16, 8, 2, + /* key */ + { 0x91, 0x94, 0x5d, 0x3f, 0x4d, 0xcb, 0xee, 0x0b, + 0xf4, 0x5e, 0xf5, 0x22, 0x55, 0xf0, 0x95, 0xa4 }, + /* nonce */ + { 0xbe, 0xca, 0xf0, 0x43, 0xb0, 0xa2, 0x3d, 0x84, + 0x31, 0x94, 0xba, 0x97, 0x2c, 0x66, 0xde, 0xbd }, + /* header */ + { 0xfa, 0x3b, 0xfd, 0x48, 0x06, 0xeb, 0x53, 0xfa }, + /* PT */ + { 0xf7, 0xfb }, + /* CT */ + { 0x19, 0xdd }, + /* tag */ + { 0x5c, 0x4c, 0x93, 0x31, 0x04, 0x9d, 0x0b, 0xda, + 0xb0, 0x27, 0x74, 0x08, 0xf6, 0x79, 0x67, 0xe5 } +}, + +{ + 16, 16, 8, 5, + /* key */ + { 0x01, 0xf7, 0x4a, 0xd6, 0x40, 0x77, 0xf2, 0xe7, + 0x04, 0xc0, 0xf6, 0x0a, 0xda, 0x3d, 0xd5, 0x23 }, + /* nonce */ + { 0x70, 0xc3, 0xdb, 0x4f, 0x0d, 0x26, 0x36, 0x84, + 0x00, 0xa1, 0x0e, 0xd0, 0x5d, 0x2b, 0xff, 0x5e }, + /* header */ + { 0x23, 0x4a, 0x34, 0x63, 0xc1, 0x26, 0x4a, 0xc6 }, + /* PT */ + { 0x1a, 0x47, 0xcb, 0x49, 0x33 }, + /* CT */ + { 0xd8, 0x51, 0xd5, 0xba, 0xe0 }, + /* Tag */ + { 0x3a, 0x59, 0xf2, 0x38, 0xa2, 0x3e, 0x39, 0x19, + 0x9d, 0xc9, 0x26, 0x66, 0x26, 0xc4, 0x0f, 0x80 } +} + +}; + int err, x, idx, res; + unsigned long len; + unsigned char outct[MAXBLOCKSIZE], outtag[MAXBLOCKSIZE]; + + /* AES can be under rijndael or aes... try to find it */ + if ((idx = find_cipher("aes")) == -1) { + if ((idx = find_cipher("rijndael")) == -1) { + return CRYPT_NOP; + } + } + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + len = sizeof(outtag); + if ((err = eax_encrypt_authenticate_memory(idx, tests[x].key, tests[x].keylen, + tests[x].nonce, tests[x].noncelen, tests[x].header, tests[x].headerlen, + tests[x].plaintext, tests[x].msglen, outct, outtag, &len)) != CRYPT_OK) { + return err; + } + if (XMEMCMP(outct, tests[x].ciphertext, tests[x].msglen) || XMEMCMP(outtag, tests[x].tag, len)) { +#if 0 + unsigned long y; + printf("\n\nFailure: \nCT:\n"); + for (y = 0; y < (unsigned long)tests[x].msglen; ) { + printf("0x%02x", outct[y]); + if (y < (unsigned long)(tests[x].msglen-1)) printf(", "); + if (!(++y % 8)) printf("\n"); + } + printf("\nTAG:\n"); + for (y = 0; y < len; ) { + printf("0x%02x", outtag[y]); + if (y < len-1) printf(", "); + if (!(++y % 8)) printf("\n"); + } +#endif + return CRYPT_FAIL_TESTVECTOR; + } + + /* test decrypt */ + if ((err = eax_decrypt_verify_memory(idx, tests[x].key, tests[x].keylen, + tests[x].nonce, tests[x].noncelen, tests[x].header, tests[x].headerlen, + outct, tests[x].msglen, outct, outtag, len, &res)) != CRYPT_OK) { + return err; + } + if ((res != 1) || XMEMCMP(outct, tests[x].plaintext, tests[x].msglen)) { +#if 0 + unsigned long y; + printf("\n\nFailure (res == %d): \nPT:\n", res); + for (y = 0; y < (unsigned long)tests[x].msglen; ) { + printf("0x%02x", outct[y]); + if (y < (unsigned long)(tests[x].msglen-1)) printf(", "); + if (!(++y % 8)) printf("\n"); + } + printf("\n\n"); +#endif + return CRYPT_FAIL_TESTVECTOR; + } + + } + return CRYPT_OK; +#endif /* LTC_TEST */ +} + +#endif /* LTC_EAX_MODE */ + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/eax/eax_test.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/eax/sub.mk b/core/lib/libtomcrypt/src/encauth/eax/sub.mk new file mode 100644 index 00000000000..0e74b948d1d --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/eax/sub.mk @@ -0,0 +1,8 @@ +srcs-y += eax_addheader.c +srcs-y += eax_decrypt.c +srcs-y += eax_decrypt_verify_memory.c +srcs-y += eax_done.c +srcs-y += eax_encrypt_authenticate_memory.c +srcs-y += eax_encrypt.c +srcs-y += eax_init.c +srcs-y += eax_test.c diff --git a/core/lib/libtomcrypt/src/encauth/gcm/gcm_add_aad.c b/core/lib/libtomcrypt/src/encauth/gcm/gcm_add_aad.c new file mode 100644 index 00000000000..b8e6285ede0 --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/gcm/gcm_add_aad.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file gcm_add_aad.c + GCM implementation, Add AAD data to the stream, by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_GCM_MODE + +/** + Add AAD to the GCM state + @param gcm The GCM state + @param adata The additional authentication data to add to the GCM state + @param adatalen The length of the AAD data. + @return CRYPT_OK on success + */ +int gcm_add_aad(gcm_state *gcm, + const unsigned char *adata, unsigned long adatalen) +{ + unsigned long x; + int err; +#ifdef LTC_FAST + unsigned long y; +#endif + + LTC_ARGCHK(gcm != NULL); + if (adatalen > 0) { + LTC_ARGCHK(adata != NULL); + } + + if (gcm->buflen > 16 || gcm->buflen < 0) { + return CRYPT_INVALID_ARG; + } + + if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) { + return err; + } + + /* in IV mode? */ + if (gcm->mode == LTC_GCM_MODE_IV) { + /* let's process the IV */ + if (gcm->ivmode || gcm->buflen != 12) { + for (x = 0; x < (unsigned long)gcm->buflen; x++) { + gcm->X[x] ^= gcm->buf[x]; + } + if (gcm->buflen) { + gcm->totlen += gcm->buflen * CONST64(8); + gcm_mult_h(gcm, gcm->X); + } + + /* mix in the length */ + zeromem(gcm->buf, 8); + STORE64H(gcm->totlen, gcm->buf+8); + for (x = 0; x < 16; x++) { + gcm->X[x] ^= gcm->buf[x]; + } + gcm_mult_h(gcm, gcm->X); + + /* copy counter out */ + XMEMCPY(gcm->Y, gcm->X, 16); + zeromem(gcm->X, 16); + } else { + XMEMCPY(gcm->Y, gcm->buf, 12); + gcm->Y[12] = 0; + gcm->Y[13] = 0; + gcm->Y[14] = 0; + gcm->Y[15] = 1; + } + XMEMCPY(gcm->Y_0, gcm->Y, 16); + zeromem(gcm->buf, 16); + gcm->buflen = 0; + gcm->totlen = 0; + gcm->mode = LTC_GCM_MODE_AAD; + } + + if (gcm->mode != LTC_GCM_MODE_AAD || gcm->buflen >= 16) { + return CRYPT_INVALID_ARG; + } + + x = 0; +#ifdef LTC_FAST + if (gcm->buflen == 0) { + for (x = 0; x < (adatalen & ~15); x += 16) { + for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE*)(&gcm->X[y])) ^= *((LTC_FAST_TYPE*)(&adata[x + y])); + } + gcm_mult_h(gcm, gcm->X); + gcm->totlen += 128; + } + adata += x; + } +#endif + + + /* start adding AAD data to the state */ + for (; x < adatalen; x++) { + gcm->X[gcm->buflen++] ^= *adata++; + + if (gcm->buflen == 16) { + /* GF mult it */ + gcm_mult_h(gcm, gcm->X); + gcm->buflen = 0; + gcm->totlen += 128; + } + } + + return CRYPT_OK; +} +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/gcm/gcm_add_aad.c,v $ */ +/* $Revision: 1.18 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/gcm/gcm_add_iv.c b/core/lib/libtomcrypt/src/encauth/gcm/gcm_add_iv.c new file mode 100644 index 00000000000..1f0b8979b47 --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/gcm/gcm_add_iv.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file gcm_add_iv.c + GCM implementation, add IV data to the state, by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_GCM_MODE + +/** + Add IV data to the GCM state + @param gcm The GCM state + @param IV The initial value data to add + @param IVlen The length of the IV + @return CRYPT_OK on success + */ +int gcm_add_iv(gcm_state *gcm, + const unsigned char *IV, unsigned long IVlen) +{ + unsigned long x, y; + int err; + + LTC_ARGCHK(gcm != NULL); + if (IVlen > 0) { + LTC_ARGCHK(IV != NULL); + } + + /* must be in IV mode */ + if (gcm->mode != LTC_GCM_MODE_IV) { + return CRYPT_INVALID_ARG; + } + + if (gcm->buflen >= 16 || gcm->buflen < 0) { + return CRYPT_INVALID_ARG; + } + + if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) { + return err; + } + + + /* trip the ivmode flag */ + if (IVlen + gcm->buflen > 12) { + gcm->ivmode |= 1; + } + + x = 0; +#ifdef LTC_FAST + if (gcm->buflen == 0) { + for (x = 0; x < (IVlen & ~15); x += 16) { + for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE*)(&gcm->X[y])) ^= *((LTC_FAST_TYPE*)(&IV[x + y])); + } + gcm_mult_h(gcm, gcm->X); + gcm->totlen += 128; + } + IV += x; + } +#endif + + /* start adding IV data to the state */ + for (; x < IVlen; x++) { + gcm->buf[gcm->buflen++] = *IV++; + + if (gcm->buflen == 16) { + /* GF mult it */ + for (y = 0; y < 16; y++) { + gcm->X[y] ^= gcm->buf[y]; + } + gcm_mult_h(gcm, gcm->X); + gcm->buflen = 0; + gcm->totlen += 128; + } + } + + return CRYPT_OK; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/gcm/gcm_add_iv.c,v $ */ +/* $Revision: 1.9 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/gcm/gcm_done.c b/core/lib/libtomcrypt/src/encauth/gcm/gcm_done.c new file mode 100644 index 00000000000..a799d750154 --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/gcm/gcm_done.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file gcm_done.c + GCM implementation, Terminate the stream, by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_GCM_MODE + +/** + Terminate a GCM stream + @param gcm The GCM state + @param tag [out] The destination for the MAC tag + @param taglen [in/out] The length of the MAC tag + @return CRYPT_OK on success + */ +int gcm_done(gcm_state *gcm, + unsigned char *tag, unsigned long *taglen) +{ + unsigned long x; + int err; + + LTC_ARGCHK(gcm != NULL); + LTC_ARGCHK(tag != NULL); + LTC_ARGCHK(taglen != NULL); + + if (gcm->buflen > 16 || gcm->buflen < 0) { + return CRYPT_INVALID_ARG; + } + + if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) { + return err; + } + + + if (gcm->mode != LTC_GCM_MODE_TEXT) { + return CRYPT_INVALID_ARG; + } + + /* handle remaining ciphertext */ + if (gcm->buflen) { + gcm->pttotlen += gcm->buflen * CONST64(8); + gcm_mult_h(gcm, gcm->X); + } + + /* length */ + STORE64H(gcm->totlen, gcm->buf); + STORE64H(gcm->pttotlen, gcm->buf+8); + for (x = 0; x < 16; x++) { + gcm->X[x] ^= gcm->buf[x]; + } + gcm_mult_h(gcm, gcm->X); + + /* encrypt original counter */ + if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y_0, gcm->buf, &gcm->K)) != CRYPT_OK) { + return err; + } + for (x = 0; x < 16 && x < *taglen; x++) { + tag[x] = gcm->buf[x] ^ gcm->X[x]; + } + *taglen = x; + + cipher_descriptor[gcm->cipher].done(&gcm->K); + + return CRYPT_OK; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/gcm/gcm_done.c,v $ */ +/* $Revision: 1.11 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/gcm/gcm_gf_mult.c b/core/lib/libtomcrypt/src/encauth/gcm/gcm_gf_mult.c new file mode 100644 index 00000000000..807c345359c --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/gcm/gcm_gf_mult.c @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file gcm_gf_mult.c + GCM implementation, do the GF mult, by Tom St Denis +*/ +#include "tomcrypt.h" + +#if defined(LTC_GCM_TABLES) || defined(LRW_TABLES) || ((defined(LTC_GCM_MODE) || defined(LTC_GCM_MODE)) && defined(LTC_FAST)) + +/* this is x*2^128 mod p(x) ... the results are 16 bytes each stored in a packed format. Since only the + * lower 16 bits are not zero'ed I removed the upper 14 bytes */ +const unsigned char gcm_shift_table[256*2] = { +0x00, 0x00, 0x01, 0xc2, 0x03, 0x84, 0x02, 0x46, 0x07, 0x08, 0x06, 0xca, 0x04, 0x8c, 0x05, 0x4e, +0x0e, 0x10, 0x0f, 0xd2, 0x0d, 0x94, 0x0c, 0x56, 0x09, 0x18, 0x08, 0xda, 0x0a, 0x9c, 0x0b, 0x5e, +0x1c, 0x20, 0x1d, 0xe2, 0x1f, 0xa4, 0x1e, 0x66, 0x1b, 0x28, 0x1a, 0xea, 0x18, 0xac, 0x19, 0x6e, +0x12, 0x30, 0x13, 0xf2, 0x11, 0xb4, 0x10, 0x76, 0x15, 0x38, 0x14, 0xfa, 0x16, 0xbc, 0x17, 0x7e, +0x38, 0x40, 0x39, 0x82, 0x3b, 0xc4, 0x3a, 0x06, 0x3f, 0x48, 0x3e, 0x8a, 0x3c, 0xcc, 0x3d, 0x0e, +0x36, 0x50, 0x37, 0x92, 0x35, 0xd4, 0x34, 0x16, 0x31, 0x58, 0x30, 0x9a, 0x32, 0xdc, 0x33, 0x1e, +0x24, 0x60, 0x25, 0xa2, 0x27, 0xe4, 0x26, 0x26, 0x23, 0x68, 0x22, 0xaa, 0x20, 0xec, 0x21, 0x2e, +0x2a, 0x70, 0x2b, 0xb2, 0x29, 0xf4, 0x28, 0x36, 0x2d, 0x78, 0x2c, 0xba, 0x2e, 0xfc, 0x2f, 0x3e, +0x70, 0x80, 0x71, 0x42, 0x73, 0x04, 0x72, 0xc6, 0x77, 0x88, 0x76, 0x4a, 0x74, 0x0c, 0x75, 0xce, +0x7e, 0x90, 0x7f, 0x52, 0x7d, 0x14, 0x7c, 0xd6, 0x79, 0x98, 0x78, 0x5a, 0x7a, 0x1c, 0x7b, 0xde, +0x6c, 0xa0, 0x6d, 0x62, 0x6f, 0x24, 0x6e, 0xe6, 0x6b, 0xa8, 0x6a, 0x6a, 0x68, 0x2c, 0x69, 0xee, +0x62, 0xb0, 0x63, 0x72, 0x61, 0x34, 0x60, 0xf6, 0x65, 0xb8, 0x64, 0x7a, 0x66, 0x3c, 0x67, 0xfe, +0x48, 0xc0, 0x49, 0x02, 0x4b, 0x44, 0x4a, 0x86, 0x4f, 0xc8, 0x4e, 0x0a, 0x4c, 0x4c, 0x4d, 0x8e, +0x46, 0xd0, 0x47, 0x12, 0x45, 0x54, 0x44, 0x96, 0x41, 0xd8, 0x40, 0x1a, 0x42, 0x5c, 0x43, 0x9e, +0x54, 0xe0, 0x55, 0x22, 0x57, 0x64, 0x56, 0xa6, 0x53, 0xe8, 0x52, 0x2a, 0x50, 0x6c, 0x51, 0xae, +0x5a, 0xf0, 0x5b, 0x32, 0x59, 0x74, 0x58, 0xb6, 0x5d, 0xf8, 0x5c, 0x3a, 0x5e, 0x7c, 0x5f, 0xbe, +0xe1, 0x00, 0xe0, 0xc2, 0xe2, 0x84, 0xe3, 0x46, 0xe6, 0x08, 0xe7, 0xca, 0xe5, 0x8c, 0xe4, 0x4e, +0xef, 0x10, 0xee, 0xd2, 0xec, 0x94, 0xed, 0x56, 0xe8, 0x18, 0xe9, 0xda, 0xeb, 0x9c, 0xea, 0x5e, +0xfd, 0x20, 0xfc, 0xe2, 0xfe, 0xa4, 0xff, 0x66, 0xfa, 0x28, 0xfb, 0xea, 0xf9, 0xac, 0xf8, 0x6e, +0xf3, 0x30, 0xf2, 0xf2, 0xf0, 0xb4, 0xf1, 0x76, 0xf4, 0x38, 0xf5, 0xfa, 0xf7, 0xbc, 0xf6, 0x7e, +0xd9, 0x40, 0xd8, 0x82, 0xda, 0xc4, 0xdb, 0x06, 0xde, 0x48, 0xdf, 0x8a, 0xdd, 0xcc, 0xdc, 0x0e, +0xd7, 0x50, 0xd6, 0x92, 0xd4, 0xd4, 0xd5, 0x16, 0xd0, 0x58, 0xd1, 0x9a, 0xd3, 0xdc, 0xd2, 0x1e, +0xc5, 0x60, 0xc4, 0xa2, 0xc6, 0xe4, 0xc7, 0x26, 0xc2, 0x68, 0xc3, 0xaa, 0xc1, 0xec, 0xc0, 0x2e, +0xcb, 0x70, 0xca, 0xb2, 0xc8, 0xf4, 0xc9, 0x36, 0xcc, 0x78, 0xcd, 0xba, 0xcf, 0xfc, 0xce, 0x3e, +0x91, 0x80, 0x90, 0x42, 0x92, 0x04, 0x93, 0xc6, 0x96, 0x88, 0x97, 0x4a, 0x95, 0x0c, 0x94, 0xce, +0x9f, 0x90, 0x9e, 0x52, 0x9c, 0x14, 0x9d, 0xd6, 0x98, 0x98, 0x99, 0x5a, 0x9b, 0x1c, 0x9a, 0xde, +0x8d, 0xa0, 0x8c, 0x62, 0x8e, 0x24, 0x8f, 0xe6, 0x8a, 0xa8, 0x8b, 0x6a, 0x89, 0x2c, 0x88, 0xee, +0x83, 0xb0, 0x82, 0x72, 0x80, 0x34, 0x81, 0xf6, 0x84, 0xb8, 0x85, 0x7a, 0x87, 0x3c, 0x86, 0xfe, +0xa9, 0xc0, 0xa8, 0x02, 0xaa, 0x44, 0xab, 0x86, 0xae, 0xc8, 0xaf, 0x0a, 0xad, 0x4c, 0xac, 0x8e, +0xa7, 0xd0, 0xa6, 0x12, 0xa4, 0x54, 0xa5, 0x96, 0xa0, 0xd8, 0xa1, 0x1a, 0xa3, 0x5c, 0xa2, 0x9e, +0xb5, 0xe0, 0xb4, 0x22, 0xb6, 0x64, 0xb7, 0xa6, 0xb2, 0xe8, 0xb3, 0x2a, 0xb1, 0x6c, 0xb0, 0xae, +0xbb, 0xf0, 0xba, 0x32, 0xb8, 0x74, 0xb9, 0xb6, 0xbc, 0xf8, 0xbd, 0x3a, 0xbf, 0x7c, 0xbe, 0xbe }; + +#endif + + +#if defined(LTC_GCM_MODE) || defined(LRW_MODE) + +#ifndef LTC_FAST +/* right shift */ +static void gcm_rightshift(unsigned char *a) +{ + int x; + for (x = 15; x > 0; x--) { + a[x] = (a[x]>>1) | ((a[x-1]<<7)&0x80); + } + a[0] >>= 1; +} + +/* c = b*a */ +static const unsigned char mask[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; +static const unsigned char poly[] = { 0x00, 0xE1 }; + + +/** + GCM GF multiplier (internal use only) bitserial + @param a First value + @param b Second value + @param c Destination for a * b + */ +void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c) +{ + unsigned char Z[16], V[16]; + unsigned x, y, z; + + zeromem(Z, 16); + XMEMCPY(V, a, 16); + for (x = 0; x < 128; x++) { + if (b[x>>3] & mask[x&7]) { + for (y = 0; y < 16; y++) { + Z[y] ^= V[y]; + } + } + z = V[15] & 0x01; + gcm_rightshift(V); + V[0] ^= poly[z]; + } + XMEMCPY(c, Z, 16); +} + +#else + +/* map normal numbers to "ieee" way ... e.g. bit reversed */ +#define M(x) ( ((x&8)>>3) | ((x&4)>>1) | ((x&2)<<1) | ((x&1)<<3) ) + +#define BPD (sizeof(LTC_FAST_TYPE) * 8) +#define WPV (1 + (16 / sizeof(LTC_FAST_TYPE))) + +/** + GCM GF multiplier (internal use only) word oriented + @param a First value + @param b Second value + @param c Destination for a * b + */ +void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c) +{ + int i, j, k, u; + LTC_FAST_TYPE B[16][WPV], tmp[32 / sizeof(LTC_FAST_TYPE)], pB[16 / sizeof(LTC_FAST_TYPE)], zz, z; + unsigned char pTmp[32]; + + /* create simple tables */ + zeromem(B[0], sizeof(B[0])); + zeromem(B[M(1)], sizeof(B[M(1)])); + +#ifdef ENDIAN_32BITWORD + for (i = 0; i < 4; i++) { + LOAD32H(B[M(1)][i], a + (i<<2)); + LOAD32L(pB[i], b + (i<<2)); + } +#else + for (i = 0; i < 2; i++) { + LOAD64H(B[M(1)][i], a + (i<<3)); + LOAD64L(pB[i], b + (i<<3)); + } +#endif + + /* now create 2, 4 and 8 */ + B[M(2)][0] = B[M(1)][0] >> 1; + B[M(4)][0] = B[M(1)][0] >> 2; + B[M(8)][0] = B[M(1)][0] >> 3; + for (i = 1; i < (int)WPV; i++) { + B[M(2)][i] = (B[M(1)][i-1] << (BPD-1)) | (B[M(1)][i] >> 1); + B[M(4)][i] = (B[M(1)][i-1] << (BPD-2)) | (B[M(1)][i] >> 2); + B[M(8)][i] = (B[M(1)][i-1] << (BPD-3)) | (B[M(1)][i] >> 3); + } + + /* now all values with two bits which are 3, 5, 6, 9, 10, 12 */ + for (i = 0; i < (int)WPV; i++) { + B[M(3)][i] = B[M(1)][i] ^ B[M(2)][i]; + B[M(5)][i] = B[M(1)][i] ^ B[M(4)][i]; + B[M(6)][i] = B[M(2)][i] ^ B[M(4)][i]; + B[M(9)][i] = B[M(1)][i] ^ B[M(8)][i]; + B[M(10)][i] = B[M(2)][i] ^ B[M(8)][i]; + B[M(12)][i] = B[M(8)][i] ^ B[M(4)][i]; + + /* now all 3 bit values and the only 4 bit value: 7, 11, 13, 14, 15 */ + B[M(7)][i] = B[M(3)][i] ^ B[M(4)][i]; + B[M(11)][i] = B[M(3)][i] ^ B[M(8)][i]; + B[M(13)][i] = B[M(1)][i] ^ B[M(12)][i]; + B[M(14)][i] = B[M(6)][i] ^ B[M(8)][i]; + B[M(15)][i] = B[M(7)][i] ^ B[M(8)][i]; + } + + zeromem(tmp, sizeof(tmp)); + + /* compute product four bits of each word at a time */ + /* for each nibble */ + for (i = (BPD/4)-1; i >= 0; i--) { + /* for each word */ + for (j = 0; j < (int)(WPV-1); j++) { + /* grab the 4 bits recall the nibbles are backwards so it's a shift by (i^1)*4 */ + u = (pB[j] >> ((i^1)<<2)) & 15; + + /* add offset by the word count the table looked up value to the result */ + for (k = 0; k < (int)WPV; k++) { + tmp[k+j] ^= B[u][k]; + } + } + /* shift result up by 4 bits */ + if (i != 0) { + for (z = j = 0; j < (int)(32 / sizeof(LTC_FAST_TYPE)); j++) { + zz = tmp[j] << (BPD-4); + tmp[j] = (tmp[j] >> 4) | z; + z = zz; + } + } + } + + /* store product */ +#ifdef ENDIAN_32BITWORD + for (i = 0; i < 8; i++) { + STORE32H(tmp[i], pTmp + (i<<2)); + } +#else + for (i = 0; i < 4; i++) { + STORE64H(tmp[i], pTmp + (i<<3)); + } +#endif + + /* reduce by taking most significant byte and adding the appropriate two byte sequence 16 bytes down */ + for (i = 31; i >= 16; i--) { + pTmp[i-16] ^= gcm_shift_table[((unsigned)pTmp[i]<<1)]; + pTmp[i-15] ^= gcm_shift_table[((unsigned)pTmp[i]<<1)+1]; + } + + for (i = 0; i < 16; i++) { + c[i] = pTmp[i]; + } + +} + +#endif + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/gcm/gcm_gf_mult.c,v $ */ +/* $Revision: 1.25 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ + diff --git a/core/lib/libtomcrypt/src/encauth/gcm/gcm_init.c b/core/lib/libtomcrypt/src/encauth/gcm/gcm_init.c new file mode 100644 index 00000000000..53ed45afb8c --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/gcm/gcm_init.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file gcm_init.c + GCM implementation, initialize state, by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_GCM_MODE + +/** + Initialize a GCM state + @param gcm The GCM state to initialize + @param cipher The index of the cipher to use + @param key The secret key + @param keylen The length of the secret key + @return CRYPT_OK on success + */ +int gcm_init(gcm_state *gcm, int cipher, + const unsigned char *key, int keylen) +{ + int err; + unsigned char B[16]; +#ifdef LTC_GCM_TABLES + int x, y, z, t; +#endif + + LTC_ARGCHK(gcm != NULL); + LTC_ARGCHK(key != NULL); + +#ifdef LTC_FAST + if (16 % sizeof(LTC_FAST_TYPE)) { + return CRYPT_INVALID_ARG; + } +#endif + + /* is cipher valid? */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + if (cipher_descriptor[cipher].block_length != 16) { + return CRYPT_INVALID_CIPHER; + } + + /* schedule key */ + if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &gcm->K)) != CRYPT_OK) { + return err; + } + + /* H = E(0) */ + zeromem(B, 16); + if ((err = cipher_descriptor[cipher].ecb_encrypt(B, gcm->H, &gcm->K)) != CRYPT_OK) { + return err; + } + + /* setup state */ + zeromem(gcm->buf, sizeof(gcm->buf)); + zeromem(gcm->X, sizeof(gcm->X)); + gcm->cipher = cipher; + gcm->mode = LTC_GCM_MODE_IV; + gcm->ivmode = 0; + gcm->buflen = 0; + gcm->totlen = 0; + gcm->pttotlen = 0; + +#ifdef LTC_GCM_TABLES + /* setup tables */ + + /* generate the first table as it has no shifting (from which we make the other tables) */ + zeromem(B, 16); + for (y = 0; y < 256; y++) { + B[0] = y; + gcm_gf_mult(gcm->H, B, &gcm->PC[0][y][0]); + } + + /* now generate the rest of the tables based the previous table */ + for (x = 1; x < 16; x++) { + for (y = 0; y < 256; y++) { + /* now shift it right by 8 bits */ + t = gcm->PC[x-1][y][15]; + for (z = 15; z > 0; z--) { + gcm->PC[x][y][z] = gcm->PC[x-1][y][z-1]; + } + gcm->PC[x][y][0] = gcm_shift_table[t<<1]; + gcm->PC[x][y][1] ^= gcm_shift_table[(t<<1)+1]; + } + } + +#endif + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/gcm/gcm_init.c,v $ */ +/* $Revision: 1.20 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/gcm/gcm_memory.c b/core/lib/libtomcrypt/src/encauth/gcm/gcm_memory.c new file mode 100644 index 00000000000..52b6dcbfd3f --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/gcm/gcm_memory.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file gcm_memory.c + GCM implementation, process a packet, by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_GCM_MODE + +/** + Process an entire GCM packet in one call. + @param cipher Index of cipher to use + @param key The secret key + @param keylen The length of the secret key + @param IV The initial vector + @param IVlen The length of the initial vector + @param adata The additional authentication data (header) + @param adatalen The length of the adata + @param pt The plaintext + @param ptlen The length of the plaintext (ciphertext length is the same) + @param ct The ciphertext + @param tag [out] The MAC tag + @param taglen [in/out] The MAC tag length + @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT) + @return CRYPT_OK on success + */ +int gcm_memory( int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *IV, unsigned long IVlen, + const unsigned char *adata, unsigned long adatalen, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen, + int direction) +{ + void *orig; + gcm_state *gcm; + int err; + + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + if (cipher_descriptor[cipher].accel_gcm_memory != NULL) { + return + cipher_descriptor[cipher].accel_gcm_memory + (key, keylen, + IV, IVlen, + adata, adatalen, + pt, ptlen, + ct, + tag, taglen, + direction); + } + + + +#ifndef LTC_GCM_TABLES_SSE2 + orig = gcm = XMALLOC(sizeof(*gcm)); +#else + orig = gcm = XMALLOC(sizeof(*gcm) + 16); +#endif + if (gcm == NULL) { + return CRYPT_MEM; + } + + /* Force GCM to be on a multiple of 16 so we can use 128-bit aligned operations + * note that we only modify gcm and keep orig intact. This code is not portable + * but again it's only for SSE2 anyways, so who cares? + */ +#ifdef LTC_GCM_TABLES_SSE2 + if ((unsigned long)gcm & 15) { + gcm = (gcm_state *)((unsigned long)gcm + (16 - ((unsigned long)gcm & 15))); + } +#endif + + if ((err = gcm_init(gcm, cipher, key, keylen)) != CRYPT_OK) { + goto LTC_ERR; + } + if ((err = gcm_add_iv(gcm, IV, IVlen)) != CRYPT_OK) { + goto LTC_ERR; + } + if ((err = gcm_add_aad(gcm, adata, adatalen)) != CRYPT_OK) { + goto LTC_ERR; + } + if ((err = gcm_process(gcm, pt, ptlen, ct, direction)) != CRYPT_OK) { + goto LTC_ERR; + } + err = gcm_done(gcm, tag, taglen); +LTC_ERR: + XFREE(orig); + return err; +} +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/gcm/gcm_memory.c,v $ */ +/* $Revision: 1.25 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/gcm/gcm_mult_h.c b/core/lib/libtomcrypt/src/encauth/gcm/gcm_mult_h.c new file mode 100644 index 00000000000..042137be548 --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/gcm/gcm_mult_h.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file gcm_mult_h.c + GCM implementation, do the GF mult, by Tom St Denis +*/ +#include "tomcrypt.h" + +#if defined(LTC_GCM_MODE) +/** + GCM multiply by H + @param gcm The GCM state which holds the H value + @param I The value to multiply H by + */ +void gcm_mult_h(gcm_state *gcm, unsigned char *I) +{ + unsigned char T[16]; +#ifdef LTC_GCM_TABLES + int x, y; +#ifdef LTC_GCM_TABLES_SSE2 + asm("movdqa (%0),%%xmm0"::"r"(&gcm->PC[0][I[0]][0])); + for (x = 1; x < 16; x++) { + asm("pxor (%0),%%xmm0"::"r"(&gcm->PC[x][I[x]][0])); + } + asm("movdqa %%xmm0,(%0)"::"r"(&T)); +#else + XMEMCPY(T, &gcm->PC[0][I[0]][0], 16); + for (x = 1; x < 16; x++) { +#ifdef LTC_FAST + for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE *)(T + y)) ^= *((LTC_FAST_TYPE *)(&gcm->PC[x][I[x]][y])); + } +#else + for (y = 0; y < 16; y++) { + T[y] ^= gcm->PC[x][I[x]][y]; + } +#endif /* LTC_FAST */ + } +#endif /* LTC_GCM_TABLES_SSE2 */ +#else + gcm_gf_mult(gcm->H, I, T); +#endif + XMEMCPY(I, T, 16); +} +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/gcm/gcm_mult_h.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/gcm/gcm_process.c b/core/lib/libtomcrypt/src/encauth/gcm/gcm_process.c new file mode 100644 index 00000000000..d2ef833a54c --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/gcm/gcm_process.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file gcm_process.c + GCM implementation, process message data, by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_GCM_MODE + +/** + Process plaintext/ciphertext through GCM + @param gcm The GCM state + @param pt The plaintext + @param ptlen The plaintext length (ciphertext length is the same) + @param ct The ciphertext + @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT) + @return CRYPT_OK on success + */ +int gcm_process(gcm_state *gcm, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + int direction) +{ + unsigned long x; + int y, err; + unsigned char b; + + LTC_ARGCHK(gcm != NULL); + if (ptlen > 0) { + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + } + + if (gcm->buflen > 16 || gcm->buflen < 0) { + return CRYPT_INVALID_ARG; + } + + if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) { + return err; + } + + /* in AAD mode? */ + if (gcm->mode == LTC_GCM_MODE_AAD) { + /* let's process the AAD */ + if (gcm->buflen) { + gcm->totlen += gcm->buflen * CONST64(8); + gcm_mult_h(gcm, gcm->X); + } + + /* increment counter */ + for (y = 15; y >= 12; y--) { + if (++gcm->Y[y] & 255) { break; } + } + /* encrypt the counter */ + if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) { + return err; + } + + gcm->buflen = 0; + gcm->mode = LTC_GCM_MODE_TEXT; + } + + if (gcm->mode != LTC_GCM_MODE_TEXT) { + return CRYPT_INVALID_ARG; + } + + x = 0; +#ifdef LTC_FAST + if (gcm->buflen == 0) { + if (direction == GCM_ENCRYPT) { + for (x = 0; x < (ptlen & ~15); x += 16) { + /* ctr encrypt */ + for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE*)(&ct[x + y])) = *((LTC_FAST_TYPE*)(&pt[x+y])) ^ *((LTC_FAST_TYPE*)(&gcm->buf[y])); + *((LTC_FAST_TYPE*)(&gcm->X[y])) ^= *((LTC_FAST_TYPE*)(&ct[x+y])); + } + /* GMAC it */ + gcm->pttotlen += 128; + gcm_mult_h(gcm, gcm->X); + /* increment counter */ + for (y = 15; y >= 12; y--) { + if (++gcm->Y[y] & 255) { break; } + } + if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) { + return err; + } + } + } else { + for (x = 0; x < (ptlen & ~15); x += 16) { + /* ctr encrypt */ + for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE*)(&gcm->X[y])) ^= *((LTC_FAST_TYPE*)(&ct[x+y])); + *((LTC_FAST_TYPE*)(&pt[x + y])) = *((LTC_FAST_TYPE*)(&ct[x+y])) ^ *((LTC_FAST_TYPE*)(&gcm->buf[y])); + } + /* GMAC it */ + gcm->pttotlen += 128; + gcm_mult_h(gcm, gcm->X); + /* increment counter */ + for (y = 15; y >= 12; y--) { + if (++gcm->Y[y] & 255) { break; } + } + if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) { + return err; + } + } + } + } +#endif + + /* process text */ + for (; x < ptlen; x++) { + if (gcm->buflen == 16) { + gcm->pttotlen += 128; + gcm_mult_h(gcm, gcm->X); + + /* increment counter */ + for (y = 15; y >= 12; y--) { + if (++gcm->Y[y] & 255) { break; } + } + if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) { + return err; + } + gcm->buflen = 0; + } + + if (direction == GCM_ENCRYPT) { + b = ct[x] = pt[x] ^ gcm->buf[gcm->buflen]; + } else { + b = ct[x]; + pt[x] = ct[x] ^ gcm->buf[gcm->buflen]; + } + gcm->X[gcm->buflen++] ^= b; + } + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/gcm/gcm_process.c,v $ */ +/* $Revision: 1.16 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/gcm/gcm_reset.c b/core/lib/libtomcrypt/src/encauth/gcm/gcm_reset.c new file mode 100644 index 00000000000..3b293b3236e --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/gcm/gcm_reset.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file gcm_reset.c + GCM implementation, reset a used state so it can accept IV data, by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_GCM_MODE + +/** + Reset a GCM state to as if you just called gcm_init(). This saves the initialization time. + @param gcm The GCM state to reset + @return CRYPT_OK on success +*/ +int gcm_reset(gcm_state *gcm) +{ + LTC_ARGCHK(gcm != NULL); + + zeromem(gcm->buf, sizeof(gcm->buf)); + zeromem(gcm->X, sizeof(gcm->X)); + gcm->mode = LTC_GCM_MODE_IV; + gcm->ivmode = 0; + gcm->buflen = 0; + gcm->totlen = 0; + gcm->pttotlen = 0; + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/gcm/gcm_reset.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/gcm/gcm_test.c b/core/lib/libtomcrypt/src/encauth/gcm/gcm_test.c new file mode 100644 index 00000000000..712fe7eca31 --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/gcm/gcm_test.c @@ -0,0 +1,440 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file gcm_test.c + GCM implementation, testing, by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_GCM_MODE + +/** + Test the GCM code + @return CRYPT_OK on success + */ +int gcm_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + unsigned char K[32]; + int keylen; + unsigned char P[128]; + unsigned long ptlen; + unsigned char A[128]; + unsigned long alen; + unsigned char IV[128]; + unsigned long IVlen; + unsigned char C[128]; + unsigned char T[16]; + } tests[] = { + +/* test case #1 */ +{ + /* key */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + 16, + + /* plaintext */ + { 0 }, + 0, + + /* AAD data */ + { 0 }, + 0, + + /* IV */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + 12, + + /* ciphertext */ + { 0 }, + + /* tag */ + { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, + 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a } +}, + +/* test case #2 */ +{ + /* key */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + 16, + + /* PT */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + 16, + + /* ADATA */ + { 0 }, + 0, + + /* IV */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + 12, + + /* CT */ + { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, + 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 }, + + /* TAG */ + { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, + 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf } +}, + +/* test case #3 */ +{ + /* key */ + { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, }, + 16, + + /* PT */ + { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55, }, + 64, + + /* ADATA */ + { 0 }, + 0, + + /* IV */ + { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88, }, + 12, + + /* CT */ + { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, + 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, + 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, + 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, + 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, + 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, + 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, + 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85, }, + + /* TAG */ + { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, + 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4, } +}, + +/* test case #4 */ +{ + /* key */ + { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, }, + 16, + + /* PT */ + { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, }, + 60, + + /* ADATA */ + { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2, }, + 20, + + /* IV */ + { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88, }, + 12, + + /* CT */ + { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, + 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, + 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, + 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, + 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, + 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, + 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, + 0x3d, 0x58, 0xe0, 0x91, }, + + /* TAG */ + { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, + 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47, } + +}, + +/* test case #5 */ +{ + /* key */ + { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, }, + 16, + + /* PT */ + { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, }, + 60, + + /* ADATA */ + { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2, }, + 20, + + /* IV */ + { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, }, + 8, + + /* CT */ + { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, + 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55, + 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, + 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23, + 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, + 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, + 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07, + 0xc2, 0x3f, 0x45, 0x98, }, + + /* TAG */ + { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, + 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb, } +}, + +/* test case #6 */ +{ + /* key */ + { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, }, + 16, + + /* PT */ + { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, }, + 60, + + /* ADATA */ + { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2, }, + 20, + + /* IV */ + { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, + 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa, + 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, + 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, + 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, + 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, + 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, + 0xa6, 0x37, 0xb3, 0x9b, }, + 60, + + /* CT */ + { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, + 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94, + 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, + 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7, + 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, + 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, + 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03, + 0x4c, 0x34, 0xae, 0xe5, }, + + /* TAG */ + { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, + 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50, } +}, + +/* test case #46 from BG (catches the LTC bug of v1.15) */ +{ + /* key */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + 16, + + /* PT */ + { 0xa2, 0xaa, 0xb3, 0xad, 0x8b, 0x17, 0xac, 0xdd, + 0xa2, 0x88, 0x42, 0x6c, 0xd7, 0xc4, 0x29, 0xb7, + 0xca, 0x86, 0xb7, 0xac, 0xa0, 0x58, 0x09, 0xc7, + 0x0c, 0xe8, 0x2d, 0xb2, 0x57, 0x11, 0xcb, 0x53, + 0x02, 0xeb, 0x27, 0x43, 0xb0, 0x36, 0xf3, 0xd7, + 0x50, 0xd6, 0xcf, 0x0d, 0xc0, 0xac, 0xb9, 0x29, + 0x50, 0xd5, 0x46, 0xdb, 0x30, 0x8f, 0x93, 0xb4, + 0xff, 0x24, 0x4a, 0xfa, 0x9d, 0xc7, 0x2b, 0xcd, + 0x75, 0x8d, 0x2c }, + 67, + + /* ADATA */ + { 0x68, 0x8e, 0x1a, 0xa9, 0x84, 0xde, 0x92, 0x6d, + 0xc7, 0xb4, 0xc4, 0x7f, 0x44 }, + 13, + + /* IV */ + { 0xb7, 0x21, 0x38, 0xb5, 0xa0, 0x5f, 0xf5, 0x07, + 0x0e, 0x8c, 0xd9, 0x41, 0x83, 0xf7, 0x61, 0xd8 }, + 16, + + /* CT */ + { 0xcb, 0xc8, 0xd2, 0xf1, 0x54, 0x81, 0xa4, 0xcc, + 0x7d, 0xd1, 0xe1, 0x9a, 0xaa, 0x83, 0xde, 0x56, + 0x78, 0x48, 0x3e, 0xc3, 0x59, 0xae, 0x7d, 0xec, + 0x2a, 0xb8, 0xd5, 0x34, 0xe0, 0x90, 0x6f, 0x4b, + 0x46, 0x63, 0xfa, 0xff, 0x58, 0xa8, 0xb2, 0xd7, + 0x33, 0xb8, 0x45, 0xee, 0xf7, 0xc9, 0xb3, 0x31, + 0xe9, 0xe1, 0x0e, 0xb2, 0x61, 0x2c, 0x99, 0x5f, + 0xeb, 0x1a, 0xc1, 0x5a, 0x62, 0x86, 0xcc, 0xe8, + 0xb2, 0x97, 0xa8 }, + + /* TAG */ + { 0x8d, 0x2d, 0x2a, 0x93, 0x72, 0x62, 0x6f, 0x6b, + 0xee, 0x85, 0x80, 0x27, 0x6a, 0x63, 0x66, 0xbf } +} + +/* rest of test cases are the same except AES key size changes... ignored... */ +}; + int idx, err; + unsigned long x, y; + unsigned char out[2][128], T[2][16]; + + /* find aes */ + idx = find_cipher("aes"); + if (idx == -1) { + idx = find_cipher("rijndael"); + if (idx == -1) { + return CRYPT_NOP; + } + } + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + y = sizeof(T[0]); + if ((err = gcm_memory(idx, tests[x].K, tests[x].keylen, + tests[x].IV, tests[x].IVlen, + tests[x].A, tests[x].alen, + (unsigned char*)tests[x].P, tests[x].ptlen, + out[0], T[0], &y, GCM_ENCRYPT)) != CRYPT_OK) { + return err; + } + + if (XMEMCMP(out[0], tests[x].C, tests[x].ptlen)) { +#if 0 + printf("\nCiphertext wrong %lu\n", x); + for (y = 0; y < tests[x].ptlen; y++) { + printf("%02x", out[0][y] & 255); + } + printf("\n"); +#endif + return CRYPT_FAIL_TESTVECTOR; + } + + if (XMEMCMP(T[0], tests[x].T, 16)) { +#if 0 + printf("\nTag on plaintext wrong %lu\n", x); + for (y = 0; y < 16; y++) { + printf("%02x", T[0][y] & 255); + } + printf("\n"); +#endif + return CRYPT_FAIL_TESTVECTOR; + } + + y = sizeof(T[1]); + if ((err = gcm_memory(idx, tests[x].K, tests[x].keylen, + tests[x].IV, tests[x].IVlen, + tests[x].A, tests[x].alen, + out[1], tests[x].ptlen, + out[0], T[1], &y, GCM_DECRYPT)) != CRYPT_OK) { + return err; + } + + if (XMEMCMP(out[1], tests[x].P, tests[x].ptlen)) { +#if 0 + printf("\nplaintext wrong %lu\n", x); + for (y = 0; y < tests[x].ptlen; y++) { + printf("%02x", out[0][y] & 255); + } + printf("\n"); +#endif + return CRYPT_FAIL_TESTVECTOR; + } + + if (XMEMCMP(T[1], tests[x].T, 16)) { +#if 0 + printf("\nTag on ciphertext wrong %lu\n", x); + for (y = 0; y < 16; y++) { + printf("%02x", T[1][y] & 255); + } + printf("\n"); +#endif + return CRYPT_FAIL_TESTVECTOR; + } + + } + return CRYPT_OK; +#endif +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/gcm/gcm_test.c,v $ */ +/* $Revision: 1.22 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/gcm/sub.mk b/core/lib/libtomcrypt/src/encauth/gcm/sub.mk new file mode 100644 index 00000000000..0da059bf31c --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/gcm/sub.mk @@ -0,0 +1,10 @@ +srcs-y += gcm_add_aad.c +srcs-y += gcm_add_iv.c +srcs-y += gcm_done.c +srcs-y += gcm_gf_mult.c +srcs-y += gcm_init.c +srcs-y += gcm_memory.c +srcs-y += gcm_mult_h.c +srcs-y += gcm_process.c +srcs-y += gcm_reset.c +srcs-y += gcm_test.c diff --git a/core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt.c b/core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt.c new file mode 100644 index 00000000000..e1d2d3a752f --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file ocb_decrypt.c + OCB implementation, decrypt data, by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_OCB_MODE + +/** + Decrypt a block with OCB. + @param ocb The OCB state + @param ct The ciphertext (length of the block size of the block cipher) + @param pt [out] The plaintext (length of ct) + @return CRYPT_OK if successful +*/ +int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt) +{ + unsigned char Z[MAXBLOCKSIZE], tmp[MAXBLOCKSIZE]; + int err, x; + + LTC_ARGCHK(ocb != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + + /* check if valid cipher */ + if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { + return err; + } + LTC_ARGCHK(cipher_descriptor[ocb->cipher].ecb_decrypt != NULL); + + /* check length */ + if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length) { + return CRYPT_INVALID_ARG; + } + + /* Get Z[i] value */ + ocb_shift_xor(ocb, Z); + + /* xor ct in, encrypt, xor Z out */ + for (x = 0; x < ocb->block_len; x++) { + tmp[x] = ct[x] ^ Z[x]; + } + if ((err = cipher_descriptor[ocb->cipher].ecb_decrypt(tmp, pt, &ocb->key)) != CRYPT_OK) { + return err; + } + for (x = 0; x < ocb->block_len; x++) { + pt[x] ^= Z[x]; + } + + /* compute checksum */ + for (x = 0; x < ocb->block_len; x++) { + ocb->checksum[x] ^= pt[x]; + } + + +#ifdef LTC_CLEAN_STACK + zeromem(Z, sizeof(Z)); + zeromem(tmp, sizeof(tmp)); +#endif + return CRYPT_OK; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/ocb/ocb_decrypt.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt_verify_memory.c b/core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt_verify_memory.c new file mode 100644 index 00000000000..c3d0efb0eb8 --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt_verify_memory.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file ocb_decrypt_verify_memory.c + OCB implementation, helper to decrypt block of memory, by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_OCB_MODE + +/** + Decrypt and compare the tag with OCB. + @param cipher The index of the cipher desired + @param key The secret key + @param keylen The length of the secret key (octets) + @param nonce The session nonce (length of the block size of the block cipher) + @param ct The ciphertext + @param ctlen The length of the ciphertext (octets) + @param pt [out] The plaintext + @param tag The tag to compare against + @param taglen The length of the tag (octets) + @param stat [out] The result of the tag comparison (1==valid, 0==invalid) + @return CRYPT_OK if successful regardless of the tag comparison +*/ +int ocb_decrypt_verify_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + const unsigned char *tag, unsigned long taglen, + int *stat) +{ + int err; + ocb_state *ocb; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(nonce != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(tag != NULL); + LTC_ARGCHK(stat != NULL); + + /* allocate memory */ + ocb = XMALLOC(sizeof(ocb_state)); + if (ocb == NULL) { + return CRYPT_MEM; + } + + if ((err = ocb_init(ocb, cipher, key, keylen, nonce)) != CRYPT_OK) { + goto LBL_ERR; + } + + while (ctlen > (unsigned long)ocb->block_len) { + if ((err = ocb_decrypt(ocb, ct, pt)) != CRYPT_OK) { + goto LBL_ERR; + } + ctlen -= ocb->block_len; + pt += ocb->block_len; + ct += ocb->block_len; + } + + err = ocb_done_decrypt(ocb, ct, ctlen, pt, tag, taglen, stat); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(ocb, sizeof(ocb_state)); +#endif + + XFREE(ocb); + + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/ocb/ocb_decrypt_verify_memory.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/ocb/ocb_done_decrypt.c b/core/lib/libtomcrypt/src/encauth/ocb/ocb_done_decrypt.c new file mode 100644 index 00000000000..336ef861a5b --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/ocb/ocb_done_decrypt.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file ocb_done_decrypt.c + OCB implementation, terminate decryption, by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_OCB_MODE + +/** + Terminate a decrypting OCB state + @param ocb The OCB state + @param ct The ciphertext (if any) + @param ctlen The length of the ciphertext (octets) + @param pt [out] The plaintext + @param tag The authentication tag (to compare against) + @param taglen The length of the authentication tag provided + @param stat [out] The result of the tag comparison + @return CRYPT_OK if the process was successful regardless if the tag is valid +*/ +int ocb_done_decrypt(ocb_state *ocb, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + const unsigned char *tag, unsigned long taglen, int *stat) +{ + int err; + unsigned char *tagbuf; + unsigned long tagbuflen; + + LTC_ARGCHK(ocb != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(tag != NULL); + LTC_ARGCHK(stat != NULL); + + /* default to failed */ + *stat = 0; + + /* allocate memory */ + tagbuf = XMALLOC(MAXBLOCKSIZE); + if (tagbuf == NULL) { + return CRYPT_MEM; + } + + tagbuflen = MAXBLOCKSIZE; + if ((err = s_ocb_done(ocb, ct, ctlen, pt, tagbuf, &tagbuflen, 1)) != CRYPT_OK) { + goto LBL_ERR; + } + + if (taglen <= tagbuflen && XMEMCMP(tagbuf, tag, taglen) == 0) { + *stat = 1; + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(tagbuf, MAXBLOCKSIZE); +#endif + + XFREE(tagbuf); + + return err; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/ocb/ocb_done_decrypt.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/ocb/ocb_done_encrypt.c b/core/lib/libtomcrypt/src/encauth/ocb/ocb_done_encrypt.c new file mode 100644 index 00000000000..ccc91293c28 --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/ocb/ocb_done_encrypt.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file ocb_done_encrypt.c + OCB implementation, terminate encryption, by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_OCB_MODE + +/** + Terminate an encryption OCB state + @param ocb The OCB state + @param pt Remaining plaintext (if any) + @param ptlen The length of the plaintext (octets) + @param ct [out] The ciphertext (if any) + @param tag [out] The tag for the OCB stream + @param taglen [in/out] The max size and resulting size of the tag + @return CRYPT_OK if successful +*/ +int ocb_done_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, unsigned char *tag, unsigned long *taglen) +{ + LTC_ARGCHK(ocb != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(tag != NULL); + LTC_ARGCHK(taglen != NULL); + return s_ocb_done(ocb, pt, ptlen, ct, tag, taglen, 0); +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/ocb/ocb_done_encrypt.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt.c b/core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt.c new file mode 100644 index 00000000000..bce2af780f5 --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file ocb_encrypt.c + OCB implementation, encrypt data, by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_OCB_MODE + +/** + Encrypt a block of data with OCB. + @param ocb The OCB state + @param pt The plaintext (length of the block size of the block cipher) + @param ct [out] The ciphertext (same size as the pt) + @return CRYPT_OK if successful +*/ +int ocb_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned char *ct) +{ + unsigned char Z[MAXBLOCKSIZE], tmp[MAXBLOCKSIZE]; + int err, x; + + LTC_ARGCHK(ocb != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { + return err; + } + if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length) { + return CRYPT_INVALID_ARG; + } + + /* compute checksum */ + for (x = 0; x < ocb->block_len; x++) { + ocb->checksum[x] ^= pt[x]; + } + + /* Get Z[i] value */ + ocb_shift_xor(ocb, Z); + + /* xor pt in, encrypt, xor Z out */ + for (x = 0; x < ocb->block_len; x++) { + tmp[x] = pt[x] ^ Z[x]; + } + if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(tmp, ct, &ocb->key)) != CRYPT_OK) { + return err; + } + for (x = 0; x < ocb->block_len; x++) { + ct[x] ^= Z[x]; + } + +#ifdef LTC_CLEAN_STACK + zeromem(Z, sizeof(Z)); + zeromem(tmp, sizeof(tmp)); +#endif + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/ocb/ocb_encrypt.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt_authenticate_memory.c b/core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt_authenticate_memory.c new file mode 100644 index 00000000000..da449458536 --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt_authenticate_memory.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file ocb_encrypt_authenticate_memory.c + OCB implementation, encrypt block of memory, by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_OCB_MODE + +/** + Encrypt and generate an authentication code for a buffer of memory + @param cipher The index of the cipher desired + @param key The secret key + @param keylen The length of the secret key (octets) + @param nonce The session nonce (length of the block ciphers block size) + @param pt The plaintext + @param ptlen The length of the plaintext (octets) + @param ct [out] The ciphertext + @param tag [out] The authentication tag + @param taglen [in/out] The max size and resulting size of the authentication tag + @return CRYPT_OK if successful +*/ +int ocb_encrypt_authenticate_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen) +{ + int err; + ocb_state *ocb; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(nonce != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(tag != NULL); + LTC_ARGCHK(taglen != NULL); + + /* allocate ram */ + ocb = XMALLOC(sizeof(ocb_state)); + if (ocb == NULL) { + return CRYPT_MEM; + } + + if ((err = ocb_init(ocb, cipher, key, keylen, nonce)) != CRYPT_OK) { + goto LBL_ERR; + } + + while (ptlen > (unsigned long)ocb->block_len) { + if ((err = ocb_encrypt(ocb, pt, ct)) != CRYPT_OK) { + goto LBL_ERR; + } + ptlen -= ocb->block_len; + pt += ocb->block_len; + ct += ocb->block_len; + } + + err = ocb_done_encrypt(ocb, pt, ptlen, ct, tag, taglen); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(ocb, sizeof(ocb_state)); +#endif + + XFREE(ocb); + + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/ocb/ocb_encrypt_authenticate_memory.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/ocb/ocb_init.c b/core/lib/libtomcrypt/src/encauth/ocb/ocb_init.c new file mode 100644 index 00000000000..0a4f95ff6fe --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/ocb/ocb_init.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file ocb_init.c + OCB implementation, initialize state, by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_OCB_MODE + +static const struct { + int len; + unsigned char poly_div[MAXBLOCKSIZE], + poly_mul[MAXBLOCKSIZE]; +} polys[] = { +{ + 8, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B } +}, { + 16, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 } +} +}; + +/** + Initialize an OCB context. + @param ocb [out] The destination of the OCB state + @param cipher The index of the desired cipher + @param key The secret key + @param keylen The length of the secret key (octets) + @param nonce The session nonce (length of the block size of the cipher) + @return CRYPT_OK if successful +*/ +int ocb_init(ocb_state *ocb, int cipher, + const unsigned char *key, unsigned long keylen, const unsigned char *nonce) +{ + int poly, x, y, m, err; + + LTC_ARGCHK(ocb != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(nonce != NULL); + + /* valid cipher? */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + /* determine which polys to use */ + ocb->block_len = cipher_descriptor[cipher].block_length; + for (poly = 0; poly < (int)(sizeof(polys)/sizeof(polys[0])); poly++) { + if (polys[poly].len == ocb->block_len) { + break; + } + } + if (polys[poly].len != ocb->block_len) { + return CRYPT_INVALID_ARG; + } + + /* schedule the key */ + if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &ocb->key)) != CRYPT_OK) { + return err; + } + + /* find L = E[0] */ + zeromem(ocb->L, ocb->block_len); + if ((err = cipher_descriptor[cipher].ecb_encrypt(ocb->L, ocb->L, &ocb->key)) != CRYPT_OK) { + return err; + } + + /* find R = E[N xor L] */ + for (x = 0; x < ocb->block_len; x++) { + ocb->R[x] = ocb->L[x] ^ nonce[x]; + } + if ((err = cipher_descriptor[cipher].ecb_encrypt(ocb->R, ocb->R, &ocb->key)) != CRYPT_OK) { + return err; + } + + /* find Ls[i] = L << i for i == 0..31 */ + XMEMCPY(ocb->Ls[0], ocb->L, ocb->block_len); + for (x = 1; x < 32; x++) { + m = ocb->Ls[x-1][0] >> 7; + for (y = 0; y < ocb->block_len-1; y++) { + ocb->Ls[x][y] = ((ocb->Ls[x-1][y] << 1) | (ocb->Ls[x-1][y+1] >> 7)) & 255; + } + ocb->Ls[x][ocb->block_len-1] = (ocb->Ls[x-1][ocb->block_len-1] << 1) & 255; + + if (m == 1) { + for (y = 0; y < ocb->block_len; y++) { + ocb->Ls[x][y] ^= polys[poly].poly_mul[y]; + } + } + } + + /* find Lr = L / x */ + m = ocb->L[ocb->block_len-1] & 1; + + /* shift right */ + for (x = ocb->block_len - 1; x > 0; x--) { + ocb->Lr[x] = ((ocb->L[x] >> 1) | (ocb->L[x-1] << 7)) & 255; + } + ocb->Lr[0] = ocb->L[0] >> 1; + + if (m == 1) { + for (x = 0; x < ocb->block_len; x++) { + ocb->Lr[x] ^= polys[poly].poly_div[x]; + } + } + + /* set Li, checksum */ + zeromem(ocb->Li, ocb->block_len); + zeromem(ocb->checksum, ocb->block_len); + + /* set other params */ + ocb->block_index = 1; + ocb->cipher = cipher; + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/ocb/ocb_init.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/ocb/ocb_ntz.c b/core/lib/libtomcrypt/src/encauth/ocb/ocb_ntz.c new file mode 100644 index 00000000000..8012d016157 --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/ocb/ocb_ntz.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file ocb_ntz.c + OCB implementation, internal function, by Tom St Denis +*/ + +#include "tomcrypt.h" + +#ifdef LTC_OCB_MODE + +/** + Returns the number of leading zero bits [from lsb up] + @param x The 32-bit value to observe + @return The number of bits [from the lsb up] that are zero +*/ +int ocb_ntz(unsigned long x) +{ + int c; + x &= 0xFFFFFFFFUL; + c = 0; + while ((x & 1) == 0) { + ++c; + x >>= 1; + } + return c; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/ocb/ocb_ntz.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/ocb/ocb_shift_xor.c b/core/lib/libtomcrypt/src/encauth/ocb/ocb_shift_xor.c new file mode 100644 index 00000000000..e5c543665af --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/ocb/ocb_shift_xor.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file ocb_shift_xor.c + OCB implementation, internal function, by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_OCB_MODE + +/** + Compute the shift/xor for OCB (internal function) + @param ocb The OCB state + @param Z The destination of the shift +*/ +void ocb_shift_xor(ocb_state *ocb, unsigned char *Z) +{ + int x, y; + y = ocb_ntz(ocb->block_index++); + for (x = 0; x < ocb->block_len; x++) { + ocb->Li[x] ^= ocb->Ls[y][x]; + Z[x] = ocb->Li[x] ^ ocb->R[x]; + } +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/ocb/ocb_shift_xor.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/ocb/ocb_test.c b/core/lib/libtomcrypt/src/encauth/ocb/ocb_test.c new file mode 100644 index 00000000000..88c4af1f43c --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/ocb/ocb_test.c @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file ocb_test.c + OCB implementation, self-test by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_OCB_MODE + +/** + Test the OCB protocol + @return CRYPT_OK if successful +*/ +int ocb_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + int ptlen; + unsigned char key[16], nonce[16], pt[34], ct[34], tag[16]; + } tests[] = { + + /* OCB-AES-128-0B */ +{ + 0, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + /* pt */ + { 0 }, + /* ct */ + { 0 }, + /* tag */ + { 0x15, 0xd3, 0x7d, 0xd7, 0xc8, 0x90, 0xd5, 0xd6, + 0xac, 0xab, 0x92, 0x7b, 0xc0, 0xdc, 0x60, 0xee }, +}, + + + /* OCB-AES-128-3B */ +{ + 3, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + /* pt */ + { 0x00, 0x01, 0x02 }, + /* ct */ + { 0xfc, 0xd3, 0x7d }, + /* tag */ + { 0x02, 0x25, 0x47, 0x39, 0xa5, 0xe3, 0x56, 0x5a, + 0xe2, 0xdc, 0xd6, 0x2c, 0x65, 0x97, 0x46, 0xba }, +}, + + /* OCB-AES-128-16B */ +{ + 16, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + /* pt */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* ct */ + { 0x37, 0xdf, 0x8c, 0xe1, 0x5b, 0x48, 0x9b, 0xf3, + 0x1d, 0x0f, 0xc4, 0x4d, 0xa1, 0xfa, 0xf6, 0xd6 }, + /* tag */ + { 0xdf, 0xb7, 0x63, 0xeb, 0xdb, 0x5f, 0x0e, 0x71, + 0x9c, 0x7b, 0x41, 0x61, 0x80, 0x80, 0x04, 0xdf }, +}, + + /* OCB-AES-128-20B */ +{ + 20, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + /* pt */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 }, + /* ct */ + { 0x01, 0xa0, 0x75, 0xf0, 0xd8, 0x15, 0xb1, 0xa4, + 0xe9, 0xc8, 0x81, 0xa1, 0xbc, 0xff, 0xc3, 0xeb, + 0x70, 0x03, 0xeb, 0x55}, + /* tag */ + { 0x75, 0x30, 0x84, 0x14, 0x4e, 0xb6, 0x3b, 0x77, + 0x0b, 0x06, 0x3c, 0x2e, 0x23, 0xcd, 0xa0, 0xbb }, +}, + + /* OCB-AES-128-32B */ +{ + 32, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + /* pt */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, + /* ct */ + { 0x01, 0xa0, 0x75, 0xf0, 0xd8, 0x15, 0xb1, 0xa4, + 0xe9, 0xc8, 0x81, 0xa1, 0xbc, 0xff, 0xc3, 0xeb, + 0x4a, 0xfc, 0xbb, 0x7f, 0xed, 0xc0, 0x8c, 0xa8, + 0x65, 0x4c, 0x6d, 0x30, 0x4d, 0x16, 0x12, 0xfa }, + + /* tag */ + { 0xc1, 0x4c, 0xbf, 0x2c, 0x1a, 0x1f, 0x1c, 0x3c, + 0x13, 0x7e, 0xad, 0xea, 0x1f, 0x2f, 0x2f, 0xcf }, +}, + + /* OCB-AES-128-34B */ +{ + 34, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + /* pt */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21 }, + /* ct */ + { 0x01, 0xa0, 0x75, 0xf0, 0xd8, 0x15, 0xb1, 0xa4, + 0xe9, 0xc8, 0x81, 0xa1, 0xbc, 0xff, 0xc3, 0xeb, + 0xd4, 0x90, 0x3d, 0xd0, 0x02, 0x5b, 0xa4, 0xaa, + 0x83, 0x7c, 0x74, 0xf1, 0x21, 0xb0, 0x26, 0x0f, + 0xa9, 0x5d }, + + /* tag */ + { 0xcf, 0x83, 0x41, 0xbb, 0x10, 0x82, 0x0c, 0xcf, + 0x14, 0xbd, 0xec, 0x56, 0xb8, 0xd7, 0xd6, 0xab }, +}, + +}; + + int err, x, idx, res; + unsigned long len; + unsigned char outct[MAXBLOCKSIZE], outtag[MAXBLOCKSIZE]; + + /* AES can be under rijndael or aes... try to find it */ + if ((idx = find_cipher("aes")) == -1) { + if ((idx = find_cipher("rijndael")) == -1) { + return CRYPT_NOP; + } + } + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + len = sizeof(outtag); + if ((err = ocb_encrypt_authenticate_memory(idx, tests[x].key, 16, + tests[x].nonce, tests[x].pt, tests[x].ptlen, outct, outtag, &len)) != CRYPT_OK) { + return err; + } + + if (XMEMCMP(outtag, tests[x].tag, len) || XMEMCMP(outct, tests[x].ct, tests[x].ptlen)) { +#if 0 + unsigned long y; + printf("\n\nFailure: \nCT:\n"); + for (y = 0; y < (unsigned long)tests[x].ptlen; ) { + printf("0x%02x", outct[y]); + if (y < (unsigned long)(tests[x].ptlen-1)) printf(", "); + if (!(++y % 8)) printf("\n"); + } + printf("\nTAG:\n"); + for (y = 0; y < len; ) { + printf("0x%02x", outtag[y]); + if (y < len-1) printf(", "); + if (!(++y % 8)) printf("\n"); + } +#endif + return CRYPT_FAIL_TESTVECTOR; + } + + if ((err = ocb_decrypt_verify_memory(idx, tests[x].key, 16, tests[x].nonce, outct, tests[x].ptlen, + outct, tests[x].tag, len, &res)) != CRYPT_OK) { + return err; + } + if ((res != 1) || XMEMCMP(tests[x].pt, outct, tests[x].ptlen)) { +#if 0 + unsigned long y; + printf("\n\nFailure-decrypt: \nPT:\n"); + for (y = 0; y < (unsigned long)tests[x].ptlen; ) { + printf("0x%02x", outct[y]); + if (y < (unsigned long)(tests[x].ptlen-1)) printf(", "); + if (!(++y % 8)) printf("\n"); + } + printf("\nres = %d\n\n", res); +#endif + } + } + return CRYPT_OK; +#endif /* LTC_TEST */ +} + +#endif /* LTC_OCB_MODE */ + + +/* some comments + + -- it's hard to seek + -- hard to stream [you can't emit ciphertext until full block] + -- The setup is somewhat complicated... +*/ + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/ocb/ocb_test.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/ocb/s_ocb_done.c b/core/lib/libtomcrypt/src/encauth/ocb/s_ocb_done.c new file mode 100644 index 00000000000..50d4af69ab2 --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/ocb/s_ocb_done.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/** + @file s_ocb_done.c + OCB implementation, internal helper, by Tom St Denis +*/ +#include "tomcrypt.h" + +#ifdef LTC_OCB_MODE + +/* Since the last block is encrypted in CTR mode the same code can + * be used to finish a decrypt or encrypt stream. The only difference + * is we XOR the final ciphertext into the checksum so we have to xor it + * before we CTR [decrypt] or after [encrypt] + * + * the names pt/ptlen/ct really just mean in/inlen/out but this is the way I wrote it... + */ + +/** + Shared code to finish an OCB stream + @param ocb The OCB state + @param pt The remaining plaintext [or input] + @param ptlen The length of the input (octets) + @param ct [out] The output buffer + @param tag [out] The destination for the authentication tag + @param taglen [in/out] The max size and resulting size of the authentication tag + @param mode The mode we are terminating, 0==encrypt, 1==decrypt + @return CRYPT_OK if successful +*/ +int s_ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, unsigned char *tag, unsigned long *taglen, int mode) + +{ + unsigned char *Z, *Y, *X; + int err, x; + + LTC_ARGCHK(ocb != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(tag != NULL); + LTC_ARGCHK(taglen != NULL); + if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { + return err; + } + if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length || + (int)ptlen > ocb->block_len || (int)ptlen < 0) { + return CRYPT_INVALID_ARG; + } + + /* allocate ram */ + Z = XMALLOC(MAXBLOCKSIZE); + Y = XMALLOC(MAXBLOCKSIZE); + X = XMALLOC(MAXBLOCKSIZE); + if (X == NULL || Y == NULL || Z == NULL) { + if (X != NULL) { + XFREE(X); + } + if (Y != NULL) { + XFREE(Y); + } + if (Z != NULL) { + XFREE(Z); + } + return CRYPT_MEM; + } + + /* compute X[m] = len(pt[m]) XOR Lr XOR Z[m] */ + ocb_shift_xor(ocb, X); + XMEMCPY(Z, X, ocb->block_len); + + X[ocb->block_len-1] ^= (ptlen*8)&255; + X[ocb->block_len-2] ^= ((ptlen*8)>>8)&255; + for (x = 0; x < ocb->block_len; x++) { + X[x] ^= ocb->Lr[x]; + } + + /* Y[m] = E(X[m])) */ + if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(X, Y, &ocb->key)) != CRYPT_OK) { + goto error; + } + + if (mode == 1) { + /* decrypt mode, so let's xor it first */ + /* xor C[m] into checksum */ + for (x = 0; x < (int)ptlen; x++) { + ocb->checksum[x] ^= ct[x]; + } + } + + /* C[m] = P[m] xor Y[m] */ + for (x = 0; x < (int)ptlen; x++) { + ct[x] = pt[x] ^ Y[x]; + } + + if (mode == 0) { + /* encrypt mode */ + /* xor C[m] into checksum */ + for (x = 0; x < (int)ptlen; x++) { + ocb->checksum[x] ^= ct[x]; + } + } + + /* xor Y[m] and Z[m] into checksum */ + for (x = 0; x < ocb->block_len; x++) { + ocb->checksum[x] ^= Y[x] ^ Z[x]; + } + + /* encrypt checksum, er... tag!! */ + if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(ocb->checksum, X, &ocb->key)) != CRYPT_OK) { + goto error; + } + cipher_descriptor[ocb->cipher].done(&ocb->key); + + /* now store it */ + for (x = 0; x < ocb->block_len && x < (int)*taglen; x++) { + tag[x] = X[x]; + } + *taglen = x; + +#ifdef LTC_CLEAN_STACK + zeromem(X, MAXBLOCKSIZE); + zeromem(Y, MAXBLOCKSIZE); + zeromem(Z, MAXBLOCKSIZE); + zeromem(ocb, sizeof(*ocb)); +#endif +error: + XFREE(X); + XFREE(Y); + XFREE(Z); + + return err; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/encauth/ocb/s_ocb_done.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/encauth/ocb/sub.mk b/core/lib/libtomcrypt/src/encauth/ocb/sub.mk new file mode 100644 index 00000000000..91486e8e8a9 --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/ocb/sub.mk @@ -0,0 +1,11 @@ +srcs-y += ocb_decrypt.c +srcs-y += ocb_decrypt_verify_memory.c +srcs-y += ocb_done_decrypt.c +srcs-y += ocb_done_encrypt.c +srcs-y += ocb_encrypt_authenticate_memory.c +srcs-y += ocb_encrypt.c +srcs-y += ocb_init.c +srcs-y += ocb_ntz.c +srcs-y += ocb_shift_xor.c +srcs-y += s_ocb_done.c +srcs-y += ocb_test.c diff --git a/core/lib/libtomcrypt/src/encauth/sub.mk b/core/lib/libtomcrypt/src/encauth/sub.mk new file mode 100644 index 00000000000..d661127f51c --- /dev/null +++ b/core/lib/libtomcrypt/src/encauth/sub.mk @@ -0,0 +1,4 @@ +subdirs-y += ccm +subdirs-y += eax +subdirs-y += gcm +subdirs-y += ocb diff --git a/core/lib/libtomcrypt/src/hashes/helper/hash_file.c b/core/lib/libtomcrypt/src/hashes/helper/hash_file.c new file mode 100644 index 00000000000..8144f684478 --- /dev/null +++ b/core/lib/libtomcrypt/src/hashes/helper/hash_file.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file hash_file.c + Hash a file, Tom St Denis +*/ + +/** + @param hash The index of the hash desired + @param fname The name of the file you wish to hash + @param out [out] The destination of the digest + @param outlen [in/out] The max size and resulting size of the message digest + @result CRYPT_OK if successful +*/ +int hash_file(int hash, const char *fname, unsigned char *out, unsigned long *outlen) +{ +#ifdef LTC_NO_FILE + return CRYPT_NOP; +#else + FILE *in; + int err; + LTC_ARGCHK(fname != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + in = fopen(fname, "rb"); + if (in == NULL) { + return CRYPT_FILE_NOTFOUND; + } + + err = hash_filehandle(hash, in, out, outlen); + if (fclose(in) != 0) { + return CRYPT_ERROR; + } + + return err; +#endif +} + + +/* $Source: /cvs/libtom/libtomcrypt/src/hashes/helper/hash_file.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:27:23 $ */ diff --git a/core/lib/libtomcrypt/src/hashes/helper/hash_filehandle.c b/core/lib/libtomcrypt/src/hashes/helper/hash_filehandle.c new file mode 100644 index 00000000000..c0a5137d6ac --- /dev/null +++ b/core/lib/libtomcrypt/src/hashes/helper/hash_filehandle.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file hash_filehandle.c + Hash open files, Tom St Denis +*/ + +/** + Hash data from an open file handle. + @param hash The index of the hash you want to use + @param in The FILE* handle of the file you want to hash + @param out [out] The destination of the digest + @param outlen [in/out] The max size and resulting size of the digest + @result CRYPT_OK if successful +*/ +int hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outlen) +{ +#ifdef LTC_NO_FILE + return CRYPT_NOP; +#else + hash_state md; + unsigned char buf[512]; + size_t x; + int err; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(in != NULL); + + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + if (*outlen < hash_descriptor[hash].hashsize) { + *outlen = hash_descriptor[hash].hashsize; + return CRYPT_BUFFER_OVERFLOW; + } + if ((err = hash_descriptor[hash].init(&md)) != CRYPT_OK) { + return err; + } + + *outlen = hash_descriptor[hash].hashsize; + do { + x = fread(buf, 1, sizeof(buf), in); + if ((err = hash_descriptor[hash].process(&md, buf, x)) != CRYPT_OK) { + return err; + } + } while (x == sizeof(buf)); + err = hash_descriptor[hash].done(&md, out); + +#ifdef LTC_CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + return err; +#endif +} + + +/* $Source: /cvs/libtom/libtomcrypt/src/hashes/helper/hash_filehandle.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:23 $ */ diff --git a/core/lib/libtomcrypt/src/hashes/helper/hash_memory.c b/core/lib/libtomcrypt/src/hashes/helper/hash_memory.c new file mode 100644 index 00000000000..2c5359d7cb8 --- /dev/null +++ b/core/lib/libtomcrypt/src/hashes/helper/hash_memory.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file hash_memory.c + Hash memory helper, Tom St Denis +*/ + +/** + Hash a block of memory and store the digest. + @param hash The index of the hash you wish to use + @param in The data you wish to hash + @param inlen The length of the data to hash (octets) + @param out [out] Where to store the digest + @param outlen [in/out] Max size and resulting size of the digest + @return CRYPT_OK if successful +*/ +int hash_memory(int hash, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) +{ + hash_state *md; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + if (*outlen < hash_descriptor[hash].hashsize) { + *outlen = hash_descriptor[hash].hashsize; + return CRYPT_BUFFER_OVERFLOW; + } + + md = XMALLOC(sizeof(hash_state)); + if (md == NULL) { + return CRYPT_MEM; + } + + if ((err = hash_descriptor[hash].init(md)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash].process(md, in, inlen)) != CRYPT_OK) { + goto LBL_ERR; + } + err = hash_descriptor[hash].done(md, out); + *outlen = hash_descriptor[hash].hashsize; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + XFREE(md); + + return err; +} + +/* $Source: /cvs/libtom/libtomcrypt/src/hashes/helper/hash_memory.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:23 $ */ diff --git a/core/lib/libtomcrypt/src/hashes/helper/hash_memory_multi.c b/core/lib/libtomcrypt/src/hashes/helper/hash_memory_multi.c new file mode 100644 index 00000000000..f5d97a8223a --- /dev/null +++ b/core/lib/libtomcrypt/src/hashes/helper/hash_memory_multi.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" +#include +/** + @file hash_memory_multi.c + Hash (multiple buffers) memory helper, Tom St Denis +*/ + +/** + Hash multiple (non-adjacent) blocks of memory at once. + @param hash The index of the hash you wish to use + @param out [out] Where to store the digest + @param outlen [in/out] Max size and resulting size of the digest + @param in The data you wish to hash + @param inlen The length of the data to hash (octets) + @param ... tuples of (data,len) pairs to hash, terminated with a (NULL,x) (x=don't care) + @return CRYPT_OK if successful +*/ +int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...) +{ + hash_state *md; + int err; + va_list args; + const unsigned char *curptr; + unsigned long curlen; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + if (*outlen < hash_descriptor[hash].hashsize) { + *outlen = hash_descriptor[hash].hashsize; + return CRYPT_BUFFER_OVERFLOW; + } + + md = XMALLOC(sizeof(hash_state)); + if (md == NULL) { + return CRYPT_MEM; + } + + if ((err = hash_descriptor[hash].init(md)) != CRYPT_OK) { + goto LBL_ERR; + } + + va_start(args, inlen); + curptr = in; + curlen = inlen; + for (;;) { + /* process buf */ + if ((err = hash_descriptor[hash].process(md, curptr, curlen)) != CRYPT_OK) { + goto LBL_ERR; + } + /* step to next */ + curptr = va_arg(args, const unsigned char*); + if (curptr == NULL) { + break; + } + curlen = va_arg(args, unsigned long); + } + err = hash_descriptor[hash].done(md, out); + *outlen = hash_descriptor[hash].hashsize; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + XFREE(md); + va_end(args); + return err; +} + +/* $Source: /cvs/libtom/libtomcrypt/src/hashes/helper/hash_memory_multi.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:23 $ */ diff --git a/core/lib/libtomcrypt/src/hashes/helper/sub.mk b/core/lib/libtomcrypt/src/hashes/helper/sub.mk new file mode 100644 index 00000000000..dee6f8b3637 --- /dev/null +++ b/core/lib/libtomcrypt/src/hashes/helper/sub.mk @@ -0,0 +1,6 @@ +cflags-y += -Wno-unused-parameter + +srcs-y += hash_file.c +srcs-y += hash_filehandle.c +srcs-y += hash_memory.c +srcs-y += hash_memory_multi.c diff --git a/core/lib/libtomcrypt/src/hashes/md5.c b/core/lib/libtomcrypt/src/hashes/md5.c new file mode 100644 index 00000000000..de6de163188 --- /dev/null +++ b/core/lib/libtomcrypt/src/hashes/md5.c @@ -0,0 +1,395 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + + +/** + @file md5.c + LTC_MD5 hash function by Tom St Denis +*/ + +#ifdef LTC_MD5 + +const struct ltc_hash_descriptor md5_desc = +{ + "md5", + 3, + 16, + 64, + + /* OID */ + { 1, 2, 840, 113549, 2, 5, }, + 6, + + &md5_init, + &md5_process, + &md5_done, + &md5_test, + NULL +}; + +#define F(x,y,z) (z ^ (x & (y ^ z))) +#define G(x,y,z) (y ^ (z & (y ^ x))) +#define H(x,y,z) (x^y^z) +#define I(x,y,z) (y^(x|(~z))) + +#ifdef LTC_SMALL_CODE + +#define FF(a,b,c,d,M,s,t) \ + a = (a + F(b,c,d) + M + t); a = ROL(a, s) + b; + +#define GG(a,b,c,d,M,s,t) \ + a = (a + G(b,c,d) + M + t); a = ROL(a, s) + b; + +#define HH(a,b,c,d,M,s,t) \ + a = (a + H(b,c,d) + M + t); a = ROL(a, s) + b; + +#define II(a,b,c,d,M,s,t) \ + a = (a + I(b,c,d) + M + t); a = ROL(a, s) + b; + +static const unsigned char Worder[64] = { + 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, + 1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12, + 5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2, + 0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9 +}; + +static const unsigned char Rorder[64] = { + 7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22, + 5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20, + 4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23, + 6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21 +}; + +static const ulong32 Korder[64] = { +0xd76aa478UL, 0xe8c7b756UL, 0x242070dbUL, 0xc1bdceeeUL, 0xf57c0fafUL, 0x4787c62aUL, 0xa8304613UL, 0xfd469501UL, +0x698098d8UL, 0x8b44f7afUL, 0xffff5bb1UL, 0x895cd7beUL, 0x6b901122UL, 0xfd987193UL, 0xa679438eUL, 0x49b40821UL, +0xf61e2562UL, 0xc040b340UL, 0x265e5a51UL, 0xe9b6c7aaUL, 0xd62f105dUL, 0x02441453UL, 0xd8a1e681UL, 0xe7d3fbc8UL, +0x21e1cde6UL, 0xc33707d6UL, 0xf4d50d87UL, 0x455a14edUL, 0xa9e3e905UL, 0xfcefa3f8UL, 0x676f02d9UL, 0x8d2a4c8aUL, +0xfffa3942UL, 0x8771f681UL, 0x6d9d6122UL, 0xfde5380cUL, 0xa4beea44UL, 0x4bdecfa9UL, 0xf6bb4b60UL, 0xbebfbc70UL, +0x289b7ec6UL, 0xeaa127faUL, 0xd4ef3085UL, 0x04881d05UL, 0xd9d4d039UL, 0xe6db99e5UL, 0x1fa27cf8UL, 0xc4ac5665UL, +0xf4292244UL, 0x432aff97UL, 0xab9423a7UL, 0xfc93a039UL, 0x655b59c3UL, 0x8f0ccc92UL, 0xffeff47dUL, 0x85845dd1UL, +0x6fa87e4fUL, 0xfe2ce6e0UL, 0xa3014314UL, 0x4e0811a1UL, 0xf7537e82UL, 0xbd3af235UL, 0x2ad7d2bbUL, 0xeb86d391UL +}; + +#else + +#define FF(a,b,c,d,M,s,t) \ + a = (a + F(b,c,d) + M + t); a = ROLc(a, s) + b; + +#define GG(a,b,c,d,M,s,t) \ + a = (a + G(b,c,d) + M + t); a = ROLc(a, s) + b; + +#define HH(a,b,c,d,M,s,t) \ + a = (a + H(b,c,d) + M + t); a = ROLc(a, s) + b; + +#define II(a,b,c,d,M,s,t) \ + a = (a + I(b,c,d) + M + t); a = ROLc(a, s) + b; + + +#endif + +#ifdef LTC_CLEAN_STACK +static int _md5_compress(hash_state *md, unsigned char *buf) +#else +static int md5_compress(hash_state *md, unsigned char *buf) +#endif +{ + ulong32 i, W[16], a, b, c, d; +#ifdef LTC_SMALL_CODE + ulong32 t; +#endif + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD32L(W[i], buf + (4*i)); + } + + /* copy state */ + a = md->md5.state[0]; + b = md->md5.state[1]; + c = md->md5.state[2]; + d = md->md5.state[3]; + +#ifdef LTC_SMALL_CODE + for (i = 0; i < 16; ++i) { + FF(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); + t = d; d = c; c = b; b = a; a = t; + } + + for (; i < 32; ++i) { + GG(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); + t = d; d = c; c = b; b = a; a = t; + } + + for (; i < 48; ++i) { + HH(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); + t = d; d = c; c = b; b = a; a = t; + } + + for (; i < 64; ++i) { + II(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); + t = d; d = c; c = b; b = a; a = t; + } + +#else + FF(a,b,c,d,W[0],7,0xd76aa478UL) + FF(d,a,b,c,W[1],12,0xe8c7b756UL) + FF(c,d,a,b,W[2],17,0x242070dbUL) + FF(b,c,d,a,W[3],22,0xc1bdceeeUL) + FF(a,b,c,d,W[4],7,0xf57c0fafUL) + FF(d,a,b,c,W[5],12,0x4787c62aUL) + FF(c,d,a,b,W[6],17,0xa8304613UL) + FF(b,c,d,a,W[7],22,0xfd469501UL) + FF(a,b,c,d,W[8],7,0x698098d8UL) + FF(d,a,b,c,W[9],12,0x8b44f7afUL) + FF(c,d,a,b,W[10],17,0xffff5bb1UL) + FF(b,c,d,a,W[11],22,0x895cd7beUL) + FF(a,b,c,d,W[12],7,0x6b901122UL) + FF(d,a,b,c,W[13],12,0xfd987193UL) + FF(c,d,a,b,W[14],17,0xa679438eUL) + FF(b,c,d,a,W[15],22,0x49b40821UL) + GG(a,b,c,d,W[1],5,0xf61e2562UL) + GG(d,a,b,c,W[6],9,0xc040b340UL) + GG(c,d,a,b,W[11],14,0x265e5a51UL) + GG(b,c,d,a,W[0],20,0xe9b6c7aaUL) + GG(a,b,c,d,W[5],5,0xd62f105dUL) + GG(d,a,b,c,W[10],9,0x02441453UL) + GG(c,d,a,b,W[15],14,0xd8a1e681UL) + GG(b,c,d,a,W[4],20,0xe7d3fbc8UL) + GG(a,b,c,d,W[9],5,0x21e1cde6UL) + GG(d,a,b,c,W[14],9,0xc33707d6UL) + GG(c,d,a,b,W[3],14,0xf4d50d87UL) + GG(b,c,d,a,W[8],20,0x455a14edUL) + GG(a,b,c,d,W[13],5,0xa9e3e905UL) + GG(d,a,b,c,W[2],9,0xfcefa3f8UL) + GG(c,d,a,b,W[7],14,0x676f02d9UL) + GG(b,c,d,a,W[12],20,0x8d2a4c8aUL) + HH(a,b,c,d,W[5],4,0xfffa3942UL) + HH(d,a,b,c,W[8],11,0x8771f681UL) + HH(c,d,a,b,W[11],16,0x6d9d6122UL) + HH(b,c,d,a,W[14],23,0xfde5380cUL) + HH(a,b,c,d,W[1],4,0xa4beea44UL) + HH(d,a,b,c,W[4],11,0x4bdecfa9UL) + HH(c,d,a,b,W[7],16,0xf6bb4b60UL) + HH(b,c,d,a,W[10],23,0xbebfbc70UL) + HH(a,b,c,d,W[13],4,0x289b7ec6UL) + HH(d,a,b,c,W[0],11,0xeaa127faUL) + HH(c,d,a,b,W[3],16,0xd4ef3085UL) + HH(b,c,d,a,W[6],23,0x04881d05UL) + HH(a,b,c,d,W[9],4,0xd9d4d039UL) + HH(d,a,b,c,W[12],11,0xe6db99e5UL) + HH(c,d,a,b,W[15],16,0x1fa27cf8UL) + HH(b,c,d,a,W[2],23,0xc4ac5665UL) + II(a,b,c,d,W[0],6,0xf4292244UL) + II(d,a,b,c,W[7],10,0x432aff97UL) + II(c,d,a,b,W[14],15,0xab9423a7UL) + II(b,c,d,a,W[5],21,0xfc93a039UL) + II(a,b,c,d,W[12],6,0x655b59c3UL) + II(d,a,b,c,W[3],10,0x8f0ccc92UL) + II(c,d,a,b,W[10],15,0xffeff47dUL) + II(b,c,d,a,W[1],21,0x85845dd1UL) + II(a,b,c,d,W[8],6,0x6fa87e4fUL) + II(d,a,b,c,W[15],10,0xfe2ce6e0UL) + II(c,d,a,b,W[6],15,0xa3014314UL) + II(b,c,d,a,W[13],21,0x4e0811a1UL) + II(a,b,c,d,W[4],6,0xf7537e82UL) + II(d,a,b,c,W[11],10,0xbd3af235UL) + II(c,d,a,b,W[2],15,0x2ad7d2bbUL) + II(b,c,d,a,W[9],21,0xeb86d391UL) +#endif + + md->md5.state[0] = md->md5.state[0] + a; + md->md5.state[1] = md->md5.state[1] + b; + md->md5.state[2] = md->md5.state[2] + c; + md->md5.state[3] = md->md5.state[3] + d; + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int md5_compress(hash_state *md, unsigned char *buf) +{ + int err; + err = _md5_compress(md, buf); + burn_stack(sizeof(ulong32) * 21); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int md5_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + md->md5.state[0] = 0x67452301UL; + md->md5.state[1] = 0xefcdab89UL; + md->md5.state[2] = 0x98badcfeUL; + md->md5.state[3] = 0x10325476UL; + md->md5.curlen = 0; + md->md5.length = 0; + return CRYPT_OK; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +HASH_PROCESS(md5_process, md5_compress, md5, 64) + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (16 bytes) + @return CRYPT_OK if successful +*/ +int md5_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->md5.curlen >= sizeof(md->md5.buf)) { + return CRYPT_INVALID_ARG; + } + + + /* increase the length of the message */ + md->md5.length += md->md5.curlen * 8; + + /* append the '1' bit */ + md->md5.buf[md->md5.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->md5.curlen > 56) { + while (md->md5.curlen < 64) { + md->md5.buf[md->md5.curlen++] = (unsigned char)0; + } + md5_compress(md, md->md5.buf); + md->md5.curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->md5.curlen < 56) { + md->md5.buf[md->md5.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64L(md->md5.length, md->md5.buf+56); + md5_compress(md, md->md5.buf); + + /* copy output */ + for (i = 0; i < 4; i++) { + STORE32L(md->md5.state[i], out+(4*i)); + } +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int md5_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + const char *msg; + unsigned char hash[16]; + } tests[] = { + { "", + { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, + 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } }, + { "a", + {0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, + 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } }, + { "abc", + { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, + 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } }, + { "message digest", + { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, + 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } }, + { "abcdefghijklmnopqrstuvwxyz", + { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, + 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, + 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } }, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", + { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, + 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } }, + { NULL, { 0 } } + }; + + int i; + unsigned char tmp[16]; + hash_state md; + + for (i = 0; tests[i].msg != NULL; i++) { + md5_init(&md); + md5_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg)); + md5_done(&md, tmp); + if (XMEMCMP(tmp, tests[i].hash, 16) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif + + + +/* $Source: /cvs/libtom/libtomcrypt/src/hashes/md5.c,v $ */ +/* $Revision: 1.10 $ */ +/* $Date: 2007/05/12 14:25:28 $ */ diff --git a/core/lib/libtomcrypt/src/hashes/sha1.c b/core/lib/libtomcrypt/src/hashes/sha1.c new file mode 100644 index 00000000000..d82d4d09623 --- /dev/null +++ b/core/lib/libtomcrypt/src/hashes/sha1.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file sha1.c + LTC_SHA1 code by Tom St Denis +*/ + + +#ifdef LTC_SHA1 + +const struct ltc_hash_descriptor sha1_desc = +{ + "sha1", + 2, + 20, + 64, + + /* OID */ + { 1, 3, 14, 3, 2, 26, }, + 6, + + &sha1_init, + &sha1_process, + &sha1_done, + &sha1_test, + NULL +}; + +#define F0(x,y,z) (z ^ (x & (y ^ z))) +#define F1(x,y,z) (x ^ y ^ z) +#define F2(x,y,z) ((x & y) | (z & (x | y))) +#define F3(x,y,z) (x ^ y ^ z) + +#ifdef LTC_CLEAN_STACK +static int _sha1_compress(hash_state *md, unsigned char *buf) +#else +static int sha1_compress(hash_state *md, unsigned char *buf) +#endif +{ + ulong32 a,b,c,d,e,W[80],i; +#ifdef LTC_SMALL_CODE + ulong32 t; +#endif + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD32H(W[i], buf + (4*i)); + } + + /* copy state */ + a = md->sha1.state[0]; + b = md->sha1.state[1]; + c = md->sha1.state[2]; + d = md->sha1.state[3]; + e = md->sha1.state[4]; + + /* expand it */ + for (i = 16; i < 80; i++) { + W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1); + } + + /* compress */ + /* round one */ + #define FF0(a,b,c,d,e,i) e = (ROLc(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROLc(b, 30); + #define FF1(a,b,c,d,e,i) e = (ROLc(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROLc(b, 30); + #define FF2(a,b,c,d,e,i) e = (ROLc(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROLc(b, 30); + #define FF3(a,b,c,d,e,i) e = (ROLc(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROLc(b, 30); + +#ifdef LTC_SMALL_CODE + + for (i = 0; i < 20; ) { + FF0(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 40; ) { + FF1(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 60; ) { + FF2(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 80; ) { + FF3(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; + } + +#else + + for (i = 0; i < 20; ) { + FF0(a,b,c,d,e,i++); + FF0(e,a,b,c,d,i++); + FF0(d,e,a,b,c,i++); + FF0(c,d,e,a,b,i++); + FF0(b,c,d,e,a,i++); + } + + /* round two */ + for (; i < 40; ) { + FF1(a,b,c,d,e,i++); + FF1(e,a,b,c,d,i++); + FF1(d,e,a,b,c,i++); + FF1(c,d,e,a,b,i++); + FF1(b,c,d,e,a,i++); + } + + /* round three */ + for (; i < 60; ) { + FF2(a,b,c,d,e,i++); + FF2(e,a,b,c,d,i++); + FF2(d,e,a,b,c,i++); + FF2(c,d,e,a,b,i++); + FF2(b,c,d,e,a,i++); + } + + /* round four */ + for (; i < 80; ) { + FF3(a,b,c,d,e,i++); + FF3(e,a,b,c,d,i++); + FF3(d,e,a,b,c,i++); + FF3(c,d,e,a,b,i++); + FF3(b,c,d,e,a,i++); + } +#endif + + #undef FF0 + #undef FF1 + #undef FF2 + #undef FF3 + + /* store */ + md->sha1.state[0] = md->sha1.state[0] + a; + md->sha1.state[1] = md->sha1.state[1] + b; + md->sha1.state[2] = md->sha1.state[2] + c; + md->sha1.state[3] = md->sha1.state[3] + d; + md->sha1.state[4] = md->sha1.state[4] + e; + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int sha1_compress(hash_state *md, unsigned char *buf) +{ + int err; + err = _sha1_compress(md, buf); + burn_stack(sizeof(ulong32) * 87); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int sha1_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + md->sha1.state[0] = 0x67452301UL; + md->sha1.state[1] = 0xefcdab89UL; + md->sha1.state[2] = 0x98badcfeUL; + md->sha1.state[3] = 0x10325476UL; + md->sha1.state[4] = 0xc3d2e1f0UL; + md->sha1.curlen = 0; + md->sha1.length = 0; + return CRYPT_OK; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +HASH_PROCESS(sha1_process, sha1_compress, sha1, 64) + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (20 bytes) + @return CRYPT_OK if successful +*/ +int sha1_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->sha1.curlen >= sizeof(md->sha1.buf)) { + return CRYPT_INVALID_ARG; + } + + /* increase the length of the message */ + md->sha1.length += md->sha1.curlen * 8; + + /* append the '1' bit */ + md->sha1.buf[md->sha1.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->sha1.curlen > 56) { + while (md->sha1.curlen < 64) { + md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; + } + sha1_compress(md, md->sha1.buf); + md->sha1.curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->sha1.curlen < 56) { + md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64H(md->sha1.length, md->sha1.buf+56); + sha1_compress(md, md->sha1.buf); + + /* copy output */ + for (i = 0; i < 5; i++) { + STORE32H(md->sha1.state[i], out+(4*i)); + } +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int sha1_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + const char *msg; + unsigned char hash[20]; + } tests[] = { + { "abc", + { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, + 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, + 0x9c, 0xd0, 0xd8, 0x9d } + }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, + 0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, + 0xE5, 0x46, 0x70, 0xF1 } + } + }; + + int i; + unsigned char tmp[20]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + sha1_init(&md); + sha1_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg)); + sha1_done(&md, tmp); + if (XMEMCMP(tmp, tests[i].hash, 20) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif + + + +/* $Source: /cvs/libtom/libtomcrypt/src/hashes/sha1.c,v $ */ +/* $Revision: 1.10 $ */ +/* $Date: 2007/05/12 14:25:28 $ */ diff --git a/core/lib/libtomcrypt/src/hashes/sha2/sha224.c b/core/lib/libtomcrypt/src/hashes/sha2/sha224.c new file mode 100644 index 00000000000..98f1a97b339 --- /dev/null +++ b/core/lib/libtomcrypt/src/hashes/sha2/sha224.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + + +#include "tomcrypt.h" + +#if defined(LTC_SHA224) +/** + @param sha224.c + LTC_SHA-224 new NIST standard based off of LTC_SHA-256 truncated to 224 bits (Tom St Denis) +*/ + +const struct ltc_hash_descriptor sha224_desc = +{ + "sha224", + 10, + 28, + 64, + + /* OID */ + { 2, 16, 840, 1, 101, 3, 4, 2, 4, }, + 9, + + &sha224_init, + &sha256_process, + &sha224_done, + &sha224_test, + NULL +}; + +/* init the sha256 er... sha224 state ;-) */ +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int sha224_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + + md->sha256.curlen = 0; + md->sha256.length = 0; + md->sha256.state[0] = 0xc1059ed8UL; + md->sha256.state[1] = 0x367cd507UL; + md->sha256.state[2] = 0x3070dd17UL; + md->sha256.state[3] = 0xf70e5939UL; + md->sha256.state[4] = 0xffc00b31UL; + md->sha256.state[5] = 0x68581511UL; + md->sha256.state[6] = 0x64f98fa7UL; + md->sha256.state[7] = 0xbefa4fa4UL; + return CRYPT_OK; +} + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (28 bytes) + @return CRYPT_OK if successful +*/ +int sha224_done(hash_state * md, unsigned char *out) +{ + unsigned char buf[32]; + int err; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + err = sha256_done(md, buf); + XMEMCPY(out, buf, 28); +#ifdef LTC_CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + return err; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int sha224_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + const char *msg; + unsigned char hash[28]; + } tests[] = { + { "abc", + { 0x23, 0x09, 0x7d, 0x22, 0x34, 0x05, 0xd8, + 0x22, 0x86, 0x42, 0xa4, 0x77, 0xbd, 0xa2, + 0x55, 0xb3, 0x2a, 0xad, 0xbc, 0xe4, 0xbd, + 0xa0, 0xb3, 0xf7, 0xe3, 0x6c, 0x9d, 0xa7 } + }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 0x75, 0x38, 0x8b, 0x16, 0x51, 0x27, 0x76, + 0xcc, 0x5d, 0xba, 0x5d, 0xa1, 0xfd, 0x89, + 0x01, 0x50, 0xb0, 0xc6, 0x45, 0x5c, 0xb4, + 0xf5, 0x8b, 0x19, 0x52, 0x52, 0x25, 0x25 } + }, + }; + + int i; + unsigned char tmp[28]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + sha224_init(&md); + sha224_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg)); + sha224_done(&md, tmp); + if (XMEMCMP(tmp, tests[i].hash, 28) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/hashes/sha2/sha224.c,v $ */ +/* $Revision: 1.10 $ */ +/* $Date: 2007/05/12 14:25:28 $ */ diff --git a/core/lib/libtomcrypt/src/hashes/sha2/sha256.c b/core/lib/libtomcrypt/src/hashes/sha2/sha256.c new file mode 100644 index 00000000000..e1e827d070b --- /dev/null +++ b/core/lib/libtomcrypt/src/hashes/sha2/sha256.c @@ -0,0 +1,363 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file sha256.c + LTC_SHA256 by Tom St Denis +*/ + +#ifdef LTC_SHA256 + +const struct ltc_hash_descriptor sha256_desc = +{ + "sha256", + 0, + 32, + 64, + + /* OID */ + { 2, 16, 840, 1, 101, 3, 4, 2, 1, }, + 9, + + &sha256_init, + &sha256_process, + &sha256_done, + &sha256_test, + NULL +}; + +#ifdef LTC_SMALL_CODE +/* the K array */ +static const ulong32 K[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, + 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, + 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, + 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, + 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, + 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, + 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, + 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, + 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, + 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; +#endif + +/* Various logical functions */ +#define Ch(x,y,z) (z ^ (x & (y ^ z))) +#define Maj(x,y,z) (((x | y) & z) | (x & y)) +#define S(x, n) RORc((x),(n)) +#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) +#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) +#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) +#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) +#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) + +/* compress 512-bits */ +#ifdef LTC_CLEAN_STACK +static int _sha256_compress(hash_state * md, unsigned char *buf) +#else +static int sha256_compress(hash_state * md, unsigned char *buf) +#endif +{ + ulong32 S[8], W[64], t0, t1; +#ifdef LTC_SMALL_CODE + ulong32 t; +#endif + int i; + + /* copy state into S */ + for (i = 0; i < 8; i++) { + S[i] = md->sha256.state[i]; + } + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD32H(W[i], buf + (4*i)); + } + + /* fill W[16..63] */ + for (i = 16; i < 64; i++) { + W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; + } + + /* Compress */ +#ifdef LTC_SMALL_CODE +#define RND(a,b,c,d,e,f,g,h,i) \ + t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ + t1 = Sigma0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; + + for (i = 0; i < 64; ++i) { + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i); + t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; + S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; + } +#else +#define RND(a,b,c,d,e,f,g,h,i,ki) \ + t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \ + t1 = Sigma0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; + + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2); + +#undef RND + +#endif + + /* feedback */ + for (i = 0; i < 8; i++) { + md->sha256.state[i] = md->sha256.state[i] + S[i]; + } + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int sha256_compress(hash_state * md, unsigned char *buf) +{ + int err; + err = _sha256_compress(md, buf); + burn_stack(sizeof(ulong32) * 74); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int sha256_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + + md->sha256.curlen = 0; + md->sha256.length = 0; + md->sha256.state[0] = 0x6A09E667UL; + md->sha256.state[1] = 0xBB67AE85UL; + md->sha256.state[2] = 0x3C6EF372UL; + md->sha256.state[3] = 0xA54FF53AUL; + md->sha256.state[4] = 0x510E527FUL; + md->sha256.state[5] = 0x9B05688CUL; + md->sha256.state[6] = 0x1F83D9ABUL; + md->sha256.state[7] = 0x5BE0CD19UL; + return CRYPT_OK; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +HASH_PROCESS(sha256_process, sha256_compress, sha256, 64) + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (32 bytes) + @return CRYPT_OK if successful +*/ +int sha256_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->sha256.curlen >= sizeof(md->sha256.buf)) { + return CRYPT_INVALID_ARG; + } + + + /* increase the length of the message */ + md->sha256.length += md->sha256.curlen * 8; + + /* append the '1' bit */ + md->sha256.buf[md->sha256.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->sha256.curlen > 56) { + while (md->sha256.curlen < 64) { + md->sha256.buf[md->sha256.curlen++] = (unsigned char)0; + } + sha256_compress(md, md->sha256.buf); + md->sha256.curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->sha256.curlen < 56) { + md->sha256.buf[md->sha256.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64H(md->sha256.length, md->sha256.buf+56); + sha256_compress(md, md->sha256.buf); + + /* copy output */ + for (i = 0; i < 8; i++) { + STORE32H(md->sha256.state[i], out+(4*i)); + } +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int sha256_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + const char *msg; + unsigned char hash[32]; + } tests[] = { + { "abc", + { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, + 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, + 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, + 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad } + }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, + 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, + 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, + 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 } + }, + }; + + int i; + unsigned char tmp[32]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + sha256_init(&md); + sha256_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg)); + sha256_done(&md, tmp); + if (XMEMCMP(tmp, tests[i].hash, 32) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif + + + +/* $Source: /cvs/libtom/libtomcrypt/src/hashes/sha2/sha256.c,v $ */ +/* $Revision: 1.11 $ */ +/* $Date: 2007/05/12 14:25:28 $ */ diff --git a/core/lib/libtomcrypt/src/hashes/sha2/sha384.c b/core/lib/libtomcrypt/src/hashes/sha2/sha384.c new file mode 100644 index 00000000000..87dca69a150 --- /dev/null +++ b/core/lib/libtomcrypt/src/hashes/sha2/sha384.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +#if defined(LTC_SHA384) +/** + @param sha384.c + LTC_SHA384 hash included in sha512.c, Tom St Denis +*/ + +const struct ltc_hash_descriptor sha384_desc = +{ + "sha384", + 4, + 48, + 128, + + /* OID */ + { 2, 16, 840, 1, 101, 3, 4, 2, 2, }, + 9, + + &sha384_init, + &sha512_process, + &sha384_done, + &sha384_test, + NULL +}; + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int sha384_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + + md->sha512.curlen = 0; + md->sha512.length = 0; + md->sha512.state[0] = CONST64(0xcbbb9d5dc1059ed8); + md->sha512.state[1] = CONST64(0x629a292a367cd507); + md->sha512.state[2] = CONST64(0x9159015a3070dd17); + md->sha512.state[3] = CONST64(0x152fecd8f70e5939); + md->sha512.state[4] = CONST64(0x67332667ffc00b31); + md->sha512.state[5] = CONST64(0x8eb44a8768581511); + md->sha512.state[6] = CONST64(0xdb0c2e0d64f98fa7); + md->sha512.state[7] = CONST64(0x47b5481dbefa4fa4); + return CRYPT_OK; +} + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (48 bytes) + @return CRYPT_OK if successful +*/ +int sha384_done(hash_state * md, unsigned char *out) +{ + unsigned char buf[64]; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->sha512.curlen >= sizeof(md->sha512.buf)) { + return CRYPT_INVALID_ARG; + } + + sha512_done(md, buf); + XMEMCPY(out, buf, 48); +#ifdef LTC_CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int sha384_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + const char *msg; + unsigned char hash[48]; + } tests[] = { + { "abc", + { 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b, + 0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07, + 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63, + 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed, + 0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23, + 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7 } + }, + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + { 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8, + 0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47, + 0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2, + 0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12, + 0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9, + 0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39 } + }, + }; + + int i; + unsigned char tmp[48]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + sha384_init(&md); + sha384_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg)); + sha384_done(&md, tmp); + if (XMEMCMP(tmp, tests[i].hash, 48) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + + +#endif + + + +/* $Source: /cvs/libtom/libtomcrypt/src/hashes/sha2/sha384.c,v $ */ +/* $Revision: 1.10 $ */ +/* $Date: 2007/05/12 14:25:28 $ */ diff --git a/core/lib/libtomcrypt/src/hashes/sha2/sha512.c b/core/lib/libtomcrypt/src/hashes/sha2/sha512.c new file mode 100644 index 00000000000..1fd2323fd55 --- /dev/null +++ b/core/lib/libtomcrypt/src/hashes/sha2/sha512.c @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @param sha512.c + LTC_SHA512 by Tom St Denis +*/ + +#ifdef LTC_SHA512 + +const struct ltc_hash_descriptor sha512_desc = +{ + "sha512", + 5, + 64, + 128, + + /* OID */ + { 2, 16, 840, 1, 101, 3, 4, 2, 3, }, + 9, + + &sha512_init, + &sha512_process, + &sha512_done, + &sha512_test, + NULL +}; + +/* the K array */ +static const ulong64 K[80] = { +CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd), +CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc), +CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019), +CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118), +CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe), +CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2), +CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1), +CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694), +CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3), +CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65), +CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483), +CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5), +CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210), +CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4), +CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725), +CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70), +CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926), +CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df), +CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8), +CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b), +CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001), +CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30), +CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910), +CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8), +CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53), +CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8), +CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb), +CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3), +CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60), +CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec), +CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9), +CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b), +CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207), +CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178), +CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6), +CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b), +CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493), +CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c), +CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a), +CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817) +}; + +/* Various logical functions */ +#define Ch(x,y,z) (z ^ (x & (y ^ z))) +#define Maj(x,y,z) (((x | y) & z) | (x & y)) +#define S(x, n) ROR64c(x, n) +#define R(x, n) (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)n)) +#define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39)) +#define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41)) +#define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7)) +#define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6)) + +/* compress 1024-bits */ +#ifdef LTC_CLEAN_STACK +static int _sha512_compress(hash_state * md, unsigned char *buf) +#else +static int sha512_compress(hash_state * md, unsigned char *buf) +#endif +{ + ulong64 S[8], W[80], t0, t1; + int i; + + /* copy state into S */ + for (i = 0; i < 8; i++) { + S[i] = md->sha512.state[i]; + } + + /* copy the state into 1024-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD64H(W[i], buf + (8*i)); + } + + /* fill W[16..79] */ + for (i = 16; i < 80; i++) { + W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; + } + + /* Compress */ +#ifdef LTC_SMALL_CODE + for (i = 0; i < 80; i++) { + t0 = S[7] + Sigma1(S[4]) + Ch(S[4], S[5], S[6]) + K[i] + W[i]; + t1 = Sigma0(S[0]) + Maj(S[0], S[1], S[2]); + S[7] = S[6]; + S[6] = S[5]; + S[5] = S[4]; + S[4] = S[3] + t0; + S[3] = S[2]; + S[2] = S[1]; + S[1] = S[0]; + S[0] = t0 + t1; + } +#else +#define RND(a,b,c,d,e,f,g,h,i) \ + t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ + t1 = Sigma0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; + + for (i = 0; i < 80; i += 8) { + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7); + } +#endif + + + /* feedback */ + for (i = 0; i < 8; i++) { + md->sha512.state[i] = md->sha512.state[i] + S[i]; + } + + return CRYPT_OK; +} + +/* compress 1024-bits */ +#ifdef LTC_CLEAN_STACK +static int sha512_compress(hash_state * md, unsigned char *buf) +{ + int err; + err = _sha512_compress(md, buf); + burn_stack(sizeof(ulong64) * 90 + sizeof(int)); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int sha512_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + md->sha512.curlen = 0; + md->sha512.length = 0; + md->sha512.state[0] = CONST64(0x6a09e667f3bcc908); + md->sha512.state[1] = CONST64(0xbb67ae8584caa73b); + md->sha512.state[2] = CONST64(0x3c6ef372fe94f82b); + md->sha512.state[3] = CONST64(0xa54ff53a5f1d36f1); + md->sha512.state[4] = CONST64(0x510e527fade682d1); + md->sha512.state[5] = CONST64(0x9b05688c2b3e6c1f); + md->sha512.state[6] = CONST64(0x1f83d9abfb41bd6b); + md->sha512.state[7] = CONST64(0x5be0cd19137e2179); + return CRYPT_OK; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +HASH_PROCESS(sha512_process, sha512_compress, sha512, 128) + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (64 bytes) + @return CRYPT_OK if successful +*/ +int sha512_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->sha512.curlen >= sizeof(md->sha512.buf)) { + return CRYPT_INVALID_ARG; + } + + /* increase the length of the message */ + md->sha512.length += md->sha512.curlen * CONST64(8); + + /* append the '1' bit */ + md->sha512.buf[md->sha512.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 112 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->sha512.curlen > 112) { + while (md->sha512.curlen < 128) { + md->sha512.buf[md->sha512.curlen++] = (unsigned char)0; + } + sha512_compress(md, md->sha512.buf); + md->sha512.curlen = 0; + } + + /* pad upto 120 bytes of zeroes + * note: that from 112 to 120 is the 64 MSB of the length. We assume that you won't hash + * > 2^64 bits of data... :-) + */ + while (md->sha512.curlen < 120) { + md->sha512.buf[md->sha512.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64H(md->sha512.length, md->sha512.buf+120); + sha512_compress(md, md->sha512.buf); + + /* copy output */ + for (i = 0; i < 8; i++) { + STORE64H(md->sha512.state[i], out+(8*i)); + } +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int sha512_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + const char *msg; + unsigned char hash[64]; + } tests[] = { + { "abc", + { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, + 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31, + 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, + 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, + 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, + 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd, + 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, + 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f } + }, + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, + 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f, + 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1, + 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18, + 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4, + 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a, + 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54, + 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 } + }, + }; + + int i; + unsigned char tmp[64]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + sha512_init(&md); + sha512_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg)); + sha512_done(&md, tmp); + if (XMEMCMP(tmp, tests[i].hash, 64) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif + + + + +/* $Source: /cvs/libtom/libtomcrypt/src/hashes/sha2/sha512.c,v $ */ +/* $Revision: 1.10 $ */ +/* $Date: 2007/05/12 14:25:28 $ */ diff --git a/core/lib/libtomcrypt/src/hashes/sha2/sub.mk b/core/lib/libtomcrypt/src/hashes/sha2/sub.mk new file mode 100644 index 00000000000..834aeabc171 --- /dev/null +++ b/core/lib/libtomcrypt/src/hashes/sha2/sub.mk @@ -0,0 +1,4 @@ +srcs-y += sha224.c +srcs-y += sha256.c +srcs-y += sha384.c +srcs-y += sha512.c diff --git a/core/lib/libtomcrypt/src/hashes/sub.mk b/core/lib/libtomcrypt/src/hashes/sub.mk new file mode 100644 index 00000000000..c0292ebc729 --- /dev/null +++ b/core/lib/libtomcrypt/src/hashes/sub.mk @@ -0,0 +1,5 @@ +srcs-y += md5.c +srcs-y += sha1.c + +subdirs-y += helper +subdirs-y += sha2 diff --git a/core/lib/libtomcrypt/src/mac/hmac/hmac_done.c b/core/lib/libtomcrypt/src/mac/hmac/hmac_done.c new file mode 100644 index 00000000000..dd08f1a28c5 --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/hmac/hmac_done.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file hmac_done.c + LTC_HMAC support, terminate stream, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +#define LTC_HMAC_BLOCKSIZE hash_descriptor[hash].blocksize + +/** + Terminate an LTC_HMAC session + @param hmac The LTC_HMAC state + @param out [out] The destination of the LTC_HMAC authentication tag + @param outlen [in/out] The max size and resulting size of the LTC_HMAC authentication tag + @return CRYPT_OK if successful +*/ +int hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen) +{ + unsigned char *buf, *isha; + unsigned long hashsize, i; + int hash, err; + + LTC_ARGCHK(hmac != NULL); + LTC_ARGCHK(out != NULL); + + /* test hash */ + hash = hmac->hash; + if((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + /* get the hash message digest size */ + hashsize = hash_descriptor[hash].hashsize; + + /* allocate buffers */ + buf = XMALLOC(LTC_HMAC_BLOCKSIZE); + isha = XMALLOC(hashsize); + if (buf == NULL || isha == NULL) { + if (buf != NULL) { + XFREE(buf); + } + if (isha != NULL) { + XFREE(isha); + } + return CRYPT_MEM; + } + + /* Get the hash of the first LTC_HMAC vector plus the data */ + if ((err = hash_descriptor[hash].done(&hmac->md, isha)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* Create the second LTC_HMAC vector vector for step (3) */ + for(i=0; i < LTC_HMAC_BLOCKSIZE; i++) { + buf[i] = hmac->key[i] ^ 0x5C; + } + + /* Now calculate the "outer" hash for step (5), (6), and (7) */ + if ((err = hash_descriptor[hash].init(&hmac->md)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash].process(&hmac->md, buf, LTC_HMAC_BLOCKSIZE)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash].process(&hmac->md, isha, hashsize)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash].done(&hmac->md, buf)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* copy to output */ + for (i = 0; i < hashsize && i < *outlen; i++) { + out[i] = buf[i]; + } + *outlen = i; + + err = CRYPT_OK; +LBL_ERR: + XFREE(hmac->key); +#ifdef LTC_CLEAN_STACK + zeromem(isha, hashsize); + zeromem(buf, hashsize); + zeromem(hmac, sizeof(*hmac)); +#endif + + XFREE(isha); + XFREE(buf); + + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/hmac/hmac_done.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/core/lib/libtomcrypt/src/mac/hmac/hmac_file.c b/core/lib/libtomcrypt/src/mac/hmac/hmac_file.c new file mode 100644 index 00000000000..03cc140d57e --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/hmac/hmac_file.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file hmac_file.c + LTC_HMAC support, process a file, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +/** + LTC_HMAC a file + @param hash The index of the hash you wish to use + @param fname The name of the file you wish to LTC_HMAC + @param key The secret key + @param keylen The length of the secret key + @param out [out] The LTC_HMAC authentication tag + @param outlen [in/out] The max size and resulting size of the authentication tag + @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled +*/ +int hmac_file(int hash, const char *fname, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen) +{ +#ifdef LTC_NO_FILE + return CRYPT_NOP; +#else + hmac_state hmac; + FILE *in; + unsigned char buf[512]; + size_t x; + int err; + + LTC_ARGCHK(fname != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + if ((err = hmac_init(&hmac, hash, key, keylen)) != CRYPT_OK) { + return err; + } + + in = fopen(fname, "rb"); + if (in == NULL) { + return CRYPT_FILE_NOTFOUND; + } + + /* process the file contents */ + do { + x = fread(buf, 1, sizeof(buf), in); + if ((err = hmac_process(&hmac, buf, (unsigned long)x)) != CRYPT_OK) { + /* we don't trap this error since we're already returning an error! */ + fclose(in); + return err; + } + } while (x == sizeof(buf)); + + if (fclose(in) != 0) { + return CRYPT_ERROR; + } + + /* get final hmac */ + if ((err = hmac_done(&hmac, out, outlen)) != CRYPT_OK) { + return err; + } + +#ifdef LTC_CLEAN_STACK + /* clear memory */ + zeromem(buf, sizeof(buf)); +#endif + return CRYPT_OK; +#endif +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/hmac/hmac_file.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/core/lib/libtomcrypt/src/mac/hmac/hmac_init.c b/core/lib/libtomcrypt/src/mac/hmac/hmac_init.c new file mode 100644 index 00000000000..f163cd7ddcd --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/hmac/hmac_init.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file hmac_init.c + LTC_HMAC support, initialize state, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +#define LTC_HMAC_BLOCKSIZE hash_descriptor[hash].blocksize + +/** + Initialize an LTC_HMAC context. + @param hmac The LTC_HMAC state + @param hash The index of the hash you want to use + @param key The secret key + @param keylen The length of the secret key (octets) + @return CRYPT_OK if successful +*/ +int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen) +{ + unsigned char *buf; + unsigned long hashsize; + unsigned long i, z; + int err; + + LTC_ARGCHK(hmac != NULL); + LTC_ARGCHK(key != NULL); + + /* valid hash? */ + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + hmac->hash = hash; + hashsize = hash_descriptor[hash].hashsize; + + /* valid key length? */ + if (keylen == 0) { + return CRYPT_INVALID_KEYSIZE; + } + + /* allocate ram for buf */ + buf = XMALLOC(LTC_HMAC_BLOCKSIZE); + if (buf == NULL) { + return CRYPT_MEM; + } + + /* allocate memory for key */ + hmac->key = XMALLOC(LTC_HMAC_BLOCKSIZE); + if (hmac->key == NULL) { + XFREE(buf); + return CRYPT_MEM; + } + + /* (1) make sure we have a large enough key */ + if(keylen > LTC_HMAC_BLOCKSIZE) { + z = LTC_HMAC_BLOCKSIZE; + if ((err = hash_memory(hash, key, keylen, hmac->key, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + if(hashsize < LTC_HMAC_BLOCKSIZE) { + zeromem((hmac->key) + hashsize, (size_t)(LTC_HMAC_BLOCKSIZE - hashsize)); + } + keylen = hashsize; + } else { + XMEMCPY(hmac->key, key, (size_t)keylen); + if(keylen < LTC_HMAC_BLOCKSIZE) { + zeromem((hmac->key) + keylen, (size_t)(LTC_HMAC_BLOCKSIZE - keylen)); + } + } + + /* Create the initial vector for step (3) */ + for(i=0; i < LTC_HMAC_BLOCKSIZE; i++) { + buf[i] = hmac->key[i] ^ 0x36; + } + + /* Pre-pend that to the hash data */ + if ((err = hash_descriptor[hash].init(&hmac->md)) != CRYPT_OK) { + goto LBL_ERR; + } + + if ((err = hash_descriptor[hash].process(&hmac->md, buf, LTC_HMAC_BLOCKSIZE)) != CRYPT_OK) { + goto LBL_ERR; + } + goto done; +LBL_ERR: + /* free the key since we failed */ + XFREE(hmac->key); +done: +#ifdef LTC_CLEAN_STACK + zeromem(buf, LTC_HMAC_BLOCKSIZE); +#endif + + XFREE(buf); + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/hmac/hmac_init.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/core/lib/libtomcrypt/src/mac/hmac/hmac_memory.c b/core/lib/libtomcrypt/src/mac/hmac/hmac_memory.c new file mode 100644 index 00000000000..fc5fe797201 --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/hmac/hmac_memory.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file hmac_memory.c + LTC_HMAC support, process a block of memory, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +/** + LTC_HMAC a block of memory to produce the authentication tag + @param hash The index of the hash to use + @param key The secret key + @param keylen The length of the secret key (octets) + @param in The data to LTC_HMAC + @param inlen The length of the data to LTC_HMAC (octets) + @param out [out] Destination of the authentication tag + @param outlen [in/out] Max size and resulting size of authentication tag + @return CRYPT_OK if successful +*/ +int hmac_memory(int hash, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + hmac_state *hmac; + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* make sure hash descriptor is valid */ + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + /* is there a descriptor? */ + if (hash_descriptor[hash].hmac_block != NULL) { + return hash_descriptor[hash].hmac_block(key, keylen, in, inlen, out, outlen); + } + + /* nope, so call the hmac functions */ + /* allocate ram for hmac state */ + hmac = XMALLOC(sizeof(hmac_state)); + if (hmac == NULL) { + return CRYPT_MEM; + } + + if ((err = hmac_init(hmac, hash, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + if ((err = hmac_process(hmac, in, inlen)) != CRYPT_OK) { + goto LBL_ERR; + } + + if ((err = hmac_done(hmac, out, outlen)) != CRYPT_OK) { + goto LBL_ERR; + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(hmac, sizeof(hmac_state)); +#endif + + XFREE(hmac); + return err; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/hmac/hmac_memory.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/core/lib/libtomcrypt/src/mac/hmac/hmac_memory_multi.c b/core/lib/libtomcrypt/src/mac/hmac/hmac_memory_multi.c new file mode 100644 index 00000000000..95d7d1e1327 --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/hmac/hmac_memory_multi.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" +#include + +/** + @file hmac_memory_multi.c + LTC_HMAC support, process multiple blocks of memory, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +/** + LTC_HMAC multiple blocks of memory to produce the authentication tag + @param hash The index of the hash to use + @param key The secret key + @param keylen The length of the secret key (octets) + @param out [out] Destination of the authentication tag + @param outlen [in/out] Max size and resulting size of authentication tag + @param in The data to LTC_HMAC + @param inlen The length of the data to LTC_HMAC (octets) + @param ... tuples of (data,len) pairs to LTC_HMAC, terminated with a (NULL,x) (x=don't care) + @return CRYPT_OK if successful +*/ +int hmac_memory_multi(int hash, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...) + +{ + hmac_state *hmac; + int err; + va_list args; + const unsigned char *curptr; + unsigned long curlen; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* allocate ram for hmac state */ + hmac = XMALLOC(sizeof(hmac_state)); + if (hmac == NULL) { + return CRYPT_MEM; + } + + if ((err = hmac_init(hmac, hash, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + va_start(args, inlen); + curptr = in; + curlen = inlen; + for (;;) { + /* process buf */ + if ((err = hmac_process(hmac, curptr, curlen)) != CRYPT_OK) { + goto LBL_ERR; + } + /* step to next */ + curptr = va_arg(args, const unsigned char*); + if (curptr == NULL) { + break; + } + curlen = va_arg(args, unsigned long); + } + if ((err = hmac_done(hmac, out, outlen)) != CRYPT_OK) { + goto LBL_ERR; + } +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(hmac, sizeof(hmac_state)); +#endif + XFREE(hmac); + va_end(args); + return err; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/hmac/hmac_memory_multi.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/core/lib/libtomcrypt/src/mac/hmac/hmac_process.c b/core/lib/libtomcrypt/src/mac/hmac/hmac_process.c new file mode 100644 index 00000000000..aa5bb42777b --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/hmac/hmac_process.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file hmac_process.c + LTC_HMAC support, process data, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +/** + Process data through LTC_HMAC + @param hmac The hmac state + @param in The data to send through LTC_HMAC + @param inlen The length of the data to LTC_HMAC (octets) + @return CRYPT_OK if successful +*/ +int hmac_process(hmac_state *hmac, const unsigned char *in, unsigned long inlen) +{ + int err; + LTC_ARGCHK(hmac != NULL); + LTC_ARGCHK(in != NULL); + if ((err = hash_is_valid(hmac->hash)) != CRYPT_OK) { + return err; + } + return hash_descriptor[hmac->hash].process(&hmac->md, in, inlen); +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/hmac/hmac_process.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/core/lib/libtomcrypt/src/mac/hmac/hmac_test.c b/core/lib/libtomcrypt/src/mac/hmac/hmac_test.c new file mode 100644 index 00000000000..3c4007b8e2a --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/hmac/hmac_test.c @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file hmac_test.c + LTC_HMAC support, self-test, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +#define LTC_HMAC_BLOCKSIZE hash_descriptor[hash].blocksize + +/* + TEST CASES SOURCE: + +Network Working Group P. Cheng +Request for Comments: 2202 IBM +Category: Informational R. Glenn + NIST + September 1997 + Test Cases for LTC_HMAC-LTC_MD5 and LTC_HMAC-LTC_SHA-1 +*/ + +/** + LTC_HMAC self-test + @return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled. +*/ +int hmac_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + unsigned char digest[MAXBLOCKSIZE]; + int i; + + static const struct hmac_test_case { + int num; + const char *algo; + unsigned char key[128]; + unsigned long keylen; + unsigned char data[128]; + unsigned long datalen; + unsigned char digest[MAXBLOCKSIZE]; + } cases[] = { + /* + 3. Test Cases for LTC_HMAC-LTC_SHA-1 + + test_case = 1 + key = 0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c + key_len = 20 + data = "Hi Ther 20 + digest = 0x4c1a03424b55e07fe7f27be1d58bb9324a9a5a04 + digest-96 = 0x4c1a03424b55e07fe7f27be1 + */ + { 5, "sha1", + {0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c}, 20, + "Test With Truncation", 20, + {0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2, + 0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04} }, + + /* + test_case = 6 + key = 0xaa repeated 80 times + key_len = 80 + data = "Test Using Larger Than Block-Size Key - Hash Key First" + data_len = 54 + digest = 0xaa4ae5e15272d00e95705637ce8a3b55ed402112 + */ + { 6, "sha1", + {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 80, + "Test Using Larger Than Block-Size Key - Hash Key First", 54, + {0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, + 0x95, 0x70, 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, + 0xed, 0x40, 0x21, 0x12} }, + + /* + test_case = 7 + key = 0xaa repeated 80 times + key_len = 80 + data = "Test Using Larger Than Block-Size Key and Larger + Than One Block-Size Data" + data_len = 73 + digest = 0xe8e99d0f45237d786d6bbaa7965c7808bbff1a91 + */ + { 7, "sha1", + {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 80, + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", 73, + {0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, + 0x6b, 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91} }, + + /* + 2. Test Cases for LTC_HMAC-LTC_MD5 + + test_case = 1 + key = 0x0b 0b 0b 0b + 0b 0b 0b 0b + 0b 0b 0b 0b + 0b 0b 0b 0b + key_len = 16 + data = "Hi There" + data_len = 8 + digest = 0x92 94 72 7a + 36 38 bb 1c + 13 f4 8e f8 + 15 8b fc 9d + */ + { 1, "md5", + {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 16, + "Hi There", 8, + {0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c, + 0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d} }, + /* + test_case = 2 + key = "Jefe" + key_len = 4 + data = "what do ya want for nothing?" + data_len = 28 + digest = 0x750c783e6ab0b503eaa86e310a5db738 + */ + { 2, "md5", + "Jefe", 4, + "what do ya want for nothing?", 28, + {0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03, + 0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38} }, + + /* + test_case = 3 + key = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + key_len 16 + data = 0xdd repeated 50 times + data_len = 50 + digest = 0x56be34521d144c88dbb8c733f0e8b3f6 + */ + { 3, "md5", + {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 16, + {0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd}, 50, + {0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88, + 0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6} }, + /* + + test_case = 4 + key = 0x0102030405060708090a0b0c0d0e0f10111213141516171819 + key_len 25 + data = 0xcd repeated 50 times + data_len = 50 + digest = 0x697eaf0aca3a3aea3a75164746ffaa79 + */ + { 4, "md5", + {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x19}, 25, + {0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd}, 50, + {0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea, + 0x3a, 0x75, 0x16, 0x47, 0x46, 0xff, 0xaa, 0x79} }, + + + /* + + test_case = 5 + key = 0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c + key_len = 16 + data = "Test With Truncation" + data_len = 20 + digest = 0x56461ef2342edc00f9bab995690efd4c + digest-96 0x56461ef2342edc00f9bab995 + */ + { 5, "md5", + {0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c}, 16, + "Test With Truncation", 20, + {0x56, 0x46, 0x1e, 0xf2, 0x34, 0x2e, 0xdc, 0x00, + 0xf9, 0xba, 0xb9, 0x95, 0x69, 0x0e, 0xfd, 0x4c} }, + + /* + + test_case = 6 + key = 0xaa repeated 80 times + key_len = 80 + data = "Test Using Larger Than Block-Size Key - Hash +Key First" + data_len = 54 + digest = 0x6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd + */ + { 6, "md5", + {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 80, + "Test Using Larger Than Block-Size Key - Hash Key First", 54, + {0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f, + 0x0b, 0x62, 0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd} }, + + /* + + test_case = 7 + key = 0xaa repeated 80 times + key_len = 80 + data = "Test Using Larger Than Block-Size Key and Larger + Than One Block-Size Data" + data_len = 73 + digest = 0x6f630fad67cda0ee1fb1f562db3aa53e + */ + { 7, "md5", + {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 80, + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", 73, + {0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee, + 0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e} } + }; + + unsigned long outlen; + int err; + int tested=0,failed=0; + for(i=0; i < (int)(sizeof(cases) / sizeof(cases[0])); i++) { + int hash = find_hash(cases[i].algo); + if (hash == -1) continue; + ++tested; + outlen = sizeof(digest); + if((err = hmac_memory(hash, cases[i].key, cases[i].keylen, cases[i].data, cases[i].datalen, digest, &outlen)) != CRYPT_OK) { +#if 0 + printf("LTC_HMAC-%s test #%d, %s\n", cases[i].algo, cases[i].num, error_to_string(err)); +#endif + return err; + } + + if(XMEMCMP(digest, cases[i].digest, (size_t)hash_descriptor[hash].hashsize) != 0) { + failed++; +#if 0 + unsigned int j; + printf("\nLTC_HMAC-%s test #%d:\n", cases[i].algo, cases[i].num); + printf( "Result: 0x"); + for(j=0; j < hash_descriptor[hash].hashsize; j++) { + printf("%2x ", digest[j]); + } + printf("\nCorrect: 0x"); + for(j=0; j < hash_descriptor[hash].hashsize; j++) { + printf("%2x ", cases[i].digest[j]); + } + printf("\n"); + return CRYPT_ERROR; +#endif + } else { + /* printf("LTC_HMAC-%s test #%d: Passed\n", cases[i].algo, cases[i].num); */ + } + } + + if (failed != 0) { + return CRYPT_FAIL_TESTVECTOR; + } else if (tested == 0) { + return CRYPT_NOP; + } else { + return CRYPT_OK; + } + #endif +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/hmac/hmac_test.c,v $ */ +/* $Revision: 1.10 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/core/lib/libtomcrypt/src/mac/hmac/sub.mk b/core/lib/libtomcrypt/src/mac/hmac/sub.mk new file mode 100644 index 00000000000..f105db0dede --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/hmac/sub.mk @@ -0,0 +1,9 @@ +cflags-y += -Wno-unused-parameter + +srcs-y += hmac_done.c +srcs-y += hmac_file.c +srcs-y += hmac_init.c +srcs-y += hmac_memory.c +srcs-y += hmac_memory_multi.c +srcs-y += hmac_process.c +srcs-y += hmac_test.c diff --git a/core/lib/libtomcrypt/src/mac/omac/omac_done.c b/core/lib/libtomcrypt/src/mac/omac/omac_done.c new file mode 100644 index 00000000000..01b4e8beda5 --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/omac/omac_done.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file omac_done.c + LTC_OMAC1 support, terminate a stream, Tom St Denis +*/ + +#ifdef LTC_OMAC + +/** + Terminate an LTC_OMAC stream + @param omac The LTC_OMAC state + @param out [out] Destination for the authentication tag + @param outlen [in/out] The max size and resulting size of the authentication tag + @return CRYPT_OK if successful +*/ +int omac_done(omac_state *omac, unsigned char *out, unsigned long *outlen) +{ + int err, mode; + unsigned x; + + LTC_ARGCHK(omac != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + if ((err = cipher_is_valid(omac->cipher_idx)) != CRYPT_OK) { + return err; + } + + if ((omac->buflen > (int)sizeof(omac->block)) || (omac->buflen < 0) || + (omac->blklen > (int)sizeof(omac->block)) || (omac->buflen > omac->blklen)) { + return CRYPT_INVALID_ARG; + } + + /* figure out mode */ + if (omac->buflen != omac->blklen) { + /* add the 0x80 byte */ + omac->block[omac->buflen++] = 0x80; + + /* pad with 0x00 */ + while (omac->buflen < omac->blklen) { + omac->block[omac->buflen++] = 0x00; + } + mode = 1; + } else { + mode = 0; + } + + /* now xor prev + Lu[mode] */ + for (x = 0; x < (unsigned)omac->blklen; x++) { + omac->block[x] ^= omac->prev[x] ^ omac->Lu[mode][x]; + } + + /* encrypt it */ + if ((err = cipher_descriptor[omac->cipher_idx].ecb_encrypt(omac->block, omac->block, &omac->key)) != CRYPT_OK) { + return err; + } + cipher_descriptor[omac->cipher_idx].done(&omac->key); + + /* output it */ + for (x = 0; x < (unsigned)omac->blklen && x < *outlen; x++) { + out[x] = omac->block[x]; + } + *outlen = x; + +#ifdef LTC_CLEAN_STACK + zeromem(omac, sizeof(*omac)); +#endif + return CRYPT_OK; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/omac/omac_done.c,v $ */ +/* $Revision: 1.9 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/core/lib/libtomcrypt/src/mac/omac/omac_file.c b/core/lib/libtomcrypt/src/mac/omac/omac_file.c new file mode 100644 index 00000000000..569e52a031a --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/omac/omac_file.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file omac_file.c + LTC_OMAC1 support, process a file, Tom St Denis +*/ + +#ifdef LTC_OMAC + +/** + LTC_OMAC a file + @param cipher The index of the cipher desired + @param key The secret key + @param keylen The length of the secret key (octets) + @param filename The name of the file you wish to LTC_OMAC + @param out [out] Where the authentication tag is to be stored + @param outlen [in/out] The max size and resulting size of the authentication tag + @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled +*/ +int omac_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *filename, + unsigned char *out, unsigned long *outlen) +{ +#ifdef LTC_NO_FILE + return CRYPT_NOP; +#else + int err, x; + omac_state omac; + FILE *in; + unsigned char buf[512]; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(filename != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + in = fopen(filename, "rb"); + if (in == NULL) { + return CRYPT_FILE_NOTFOUND; + } + + if ((err = omac_init(&omac, cipher, key, keylen)) != CRYPT_OK) { + fclose(in); + return err; + } + + do { + x = fread(buf, 1, sizeof(buf), in); + if ((err = omac_process(&omac, buf, x)) != CRYPT_OK) { + fclose(in); + return err; + } + } while (x == sizeof(buf)); + fclose(in); + + if ((err = omac_done(&omac, out, outlen)) != CRYPT_OK) { + return err; + } + +#ifdef LTC_CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + + return CRYPT_OK; +#endif +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/omac/omac_file.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/core/lib/libtomcrypt/src/mac/omac/omac_init.c b/core/lib/libtomcrypt/src/mac/omac/omac_init.c new file mode 100644 index 00000000000..2f7d85b8f06 --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/omac/omac_init.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file omac_init.c + LTC_OMAC1 support, initialize state, by Tom St Denis +*/ + + +#ifdef LTC_OMAC + +/** + Initialize an LTC_OMAC state + @param omac The LTC_OMAC state to initialize + @param cipher The index of the desired cipher + @param key The secret key + @param keylen The length of the secret key (octets) + @return CRYPT_OK if successful +*/ +int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen) +{ + int err, x, y, mask, msb, len; + + LTC_ARGCHK(omac != NULL); + LTC_ARGCHK(key != NULL); + + /* schedule the key */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + +#ifdef LTC_FAST + if (cipher_descriptor[cipher].block_length % sizeof(LTC_FAST_TYPE)) { + return CRYPT_INVALID_ARG; + } +#endif + + /* now setup the system */ + switch (cipher_descriptor[cipher].block_length) { + case 8: mask = 0x1B; + len = 8; + break; + case 16: mask = 0x87; + len = 16; + break; + default: return CRYPT_INVALID_ARG; + } + + if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &omac->key)) != CRYPT_OK) { + return err; + } + + /* ok now we need Lu and Lu^2 [calc one from the other] */ + + /* first calc L which is Ek(0) */ + zeromem(omac->Lu[0], cipher_descriptor[cipher].block_length); + if ((err = cipher_descriptor[cipher].ecb_encrypt(omac->Lu[0], omac->Lu[0], &omac->key)) != CRYPT_OK) { + return err; + } + + /* now do the mults, whoopy! */ + for (x = 0; x < 2; x++) { + /* if msb(L * u^(x+1)) = 0 then just shift, otherwise shift and xor constant mask */ + msb = omac->Lu[x][0] >> 7; + + /* shift left */ + for (y = 0; y < (len - 1); y++) { + omac->Lu[x][y] = ((omac->Lu[x][y] << 1) | (omac->Lu[x][y+1] >> 7)) & 255; + } + omac->Lu[x][len - 1] = ((omac->Lu[x][len - 1] << 1) ^ (msb ? mask : 0)) & 255; + + /* copy up as require */ + if (x == 0) { + XMEMCPY(omac->Lu[1], omac->Lu[0], sizeof(omac->Lu[0])); + } + } + + /* setup state */ + omac->cipher_idx = cipher; + omac->buflen = 0; + omac->blklen = len; + zeromem(omac->prev, sizeof(omac->prev)); + zeromem(omac->block, sizeof(omac->block)); + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/omac/omac_init.c,v $ */ +/* $Revision: 1.12 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/core/lib/libtomcrypt/src/mac/omac/omac_memory.c b/core/lib/libtomcrypt/src/mac/omac/omac_memory.c new file mode 100644 index 00000000000..ee0ce2a489c --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/omac/omac_memory.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file omac_memory.c + LTC_OMAC1 support, process a block of memory, Tom St Denis +*/ + +#ifdef LTC_OMAC + +/** + LTC_OMAC a block of memory + @param cipher The index of the desired cipher + @param key The secret key + @param keylen The length of the secret key (octets) + @param in The data to send through LTC_OMAC + @param inlen The length of the data to send through LTC_OMAC (octets) + @param out [out] The destination of the authentication tag + @param outlen [in/out] The max size and resulting size of the authentication tag (octets) + @return CRYPT_OK if successful +*/ +int omac_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + int err; + omac_state *omac; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* is the cipher valid? */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + /* Use accelerator if found */ + if (cipher_descriptor[cipher].omac_memory != NULL) { + return cipher_descriptor[cipher].omac_memory(key, keylen, in, inlen, out, outlen); + } + + /* allocate ram for omac state */ + omac = XMALLOC(sizeof(omac_state)); + if (omac == NULL) { + return CRYPT_MEM; + } + + /* omac process the message */ + if ((err = omac_init(omac, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = omac_process(omac, in, inlen)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = omac_done(omac, out, outlen)) != CRYPT_OK) { + goto LBL_ERR; + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(omac, sizeof(omac_state)); +#endif + + XFREE(omac); + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/omac/omac_memory.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/core/lib/libtomcrypt/src/mac/omac/omac_memory_multi.c b/core/lib/libtomcrypt/src/mac/omac/omac_memory_multi.c new file mode 100644 index 00000000000..3739b8dad5d --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/omac/omac_memory_multi.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" +#include + +/** + @file omac_memory_multi.c + LTC_OMAC1 support, process multiple blocks of memory, Tom St Denis +*/ + +#ifdef LTC_OMAC + +/** + LTC_OMAC multiple blocks of memory + @param cipher The index of the desired cipher + @param key The secret key + @param keylen The length of the secret key (octets) + @param out [out] The destination of the authentication tag + @param outlen [in/out] The max size and resulting size of the authentication tag (octets) + @param in The data to send through LTC_OMAC + @param inlen The length of the data to send through LTC_OMAC (octets) + @param ... tuples of (data,len) pairs to LTC_OMAC, terminated with a (NULL,x) (x=don't care) + @return CRYPT_OK if successful +*/ +int omac_memory_multi(int cipher, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...) +{ + int err; + omac_state *omac; + va_list args; + const unsigned char *curptr; + unsigned long curlen; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* allocate ram for omac state */ + omac = XMALLOC(sizeof(omac_state)); + if (omac == NULL) { + return CRYPT_MEM; + } + + /* omac process the message */ + if ((err = omac_init(omac, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + va_start(args, inlen); + curptr = in; + curlen = inlen; + for (;;) { + /* process buf */ + if ((err = omac_process(omac, curptr, curlen)) != CRYPT_OK) { + goto LBL_ERR; + } + /* step to next */ + curptr = va_arg(args, const unsigned char*); + if (curptr == NULL) { + break; + } + curlen = va_arg(args, unsigned long); + } + if ((err = omac_done(omac, out, outlen)) != CRYPT_OK) { + goto LBL_ERR; + } +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(omac, sizeof(omac_state)); +#endif + XFREE(omac); + va_end(args); + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/omac/omac_memory_multi.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/core/lib/libtomcrypt/src/mac/omac/omac_process.c b/core/lib/libtomcrypt/src/mac/omac/omac_process.c new file mode 100644 index 00000000000..b8a4203f9b5 --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/omac/omac_process.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file omac_process.c + LTC_OMAC1 support, process data, Tom St Denis +*/ + + +#ifdef LTC_OMAC + +/** + Process data through LTC_OMAC + @param omac The LTC_OMAC state + @param in The input data to send through LTC_OMAC + @param inlen The length of the input (octets) + @return CRYPT_OK if successful +*/ +int omac_process(omac_state *omac, const unsigned char *in, unsigned long inlen) +{ + unsigned long n, x; + int err; + + LTC_ARGCHK(omac != NULL); + LTC_ARGCHK(in != NULL); + if ((err = cipher_is_valid(omac->cipher_idx)) != CRYPT_OK) { + return err; + } + + if ((omac->buflen > (int)sizeof(omac->block)) || (omac->buflen < 0) || + (omac->blklen > (int)sizeof(omac->block)) || (omac->buflen > omac->blklen)) { + return CRYPT_INVALID_ARG; + } + +#ifdef LTC_FAST + unsigned long blklen = cipher_descriptor[omac->cipher_idx].block_length; + if (omac->buflen == 0 && inlen > blklen) { + unsigned long y; + for (x = 0; x < (inlen - blklen); x += blklen) { + for (y = 0; y < blklen; y += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE*)(&omac->prev[y])) ^= *((LTC_FAST_TYPE*)(&in[y])); + } + in += blklen; + if ((err = cipher_descriptor[omac->cipher_idx].ecb_encrypt(omac->prev, omac->prev, &omac->key)) != CRYPT_OK) { + return err; + } + } + inlen -= x; + } +#endif + + while (inlen != 0) { + /* ok if the block is full we xor in prev, encrypt and replace prev */ + if (omac->buflen == omac->blklen) { + for (x = 0; x < (unsigned long)omac->blklen; x++) { + omac->block[x] ^= omac->prev[x]; + } + if ((err = cipher_descriptor[omac->cipher_idx].ecb_encrypt(omac->block, omac->prev, &omac->key)) != CRYPT_OK) { + return err; + } + omac->buflen = 0; + } + + /* add bytes */ + n = MIN(inlen, (unsigned long)(omac->blklen - omac->buflen)); + XMEMCPY(omac->block + omac->buflen, in, n); + omac->buflen += n; + inlen -= n; + in += n; + } + + return CRYPT_OK; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/omac/omac_process.c,v $ */ +/* $Revision: 1.13 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/core/lib/libtomcrypt/src/mac/omac/omac_test.c b/core/lib/libtomcrypt/src/mac/omac/omac_test.c new file mode 100644 index 00000000000..e4efb76207c --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/omac/omac_test.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file omac_test.c + LTC_OMAC1 support, self-test, by Tom St Denis +*/ + +#ifdef LTC_OMAC + +/** + Test the LTC_OMAC setup + @return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled +*/ +int omac_test(void) +{ +#if !defined(LTC_TEST) + return CRYPT_NOP; +#else + static const struct { + int keylen, msglen; + unsigned char key[16], msg[64], tag[16]; + } tests[] = { + { 16, 0, + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, + { 0x00 }, + { 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, + 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 } + }, + { 16, 16, + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, + { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a }, + { 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, + 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c } + }, + { 16, 40, + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, + { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11 }, + { 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30, + 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27 } + }, + { 16, 64, + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, + { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }, + { 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, + 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe } + } + + }; + unsigned char out[16]; + int x, err, idx; + unsigned long len; + + + /* AES can be under rijndael or aes... try to find it */ + if ((idx = find_cipher("aes")) == -1) { + if ((idx = find_cipher("rijndael")) == -1) { + return CRYPT_NOP; + } + } + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + len = sizeof(out); + if ((err = omac_memory(idx, tests[x].key, tests[x].keylen, tests[x].msg, tests[x].msglen, out, &len)) != CRYPT_OK) { + return err; + } + + if (XMEMCMP(out, tests[x].tag, 16) != 0) { +#if 0 + int y; + printf("\n\nTag: "); + for (y = 0; y < 16; y++) printf("%02x", out[y]); printf("\n\n"); +#endif + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/omac/omac_test.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/core/lib/libtomcrypt/src/mac/omac/sub.mk b/core/lib/libtomcrypt/src/mac/omac/sub.mk new file mode 100644 index 00000000000..474a3baada8 --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/omac/sub.mk @@ -0,0 +1,9 @@ +cflags-y += -Wno-unused-parameter + +srcs-y += omac_done.c +srcs-y += omac_file.c +srcs-y += omac_init.c +srcs-y += omac_memory.c +srcs-y += omac_memory_multi.c +srcs-y += omac_process.c +srcs-y += omac_test.c diff --git a/core/lib/libtomcrypt/src/mac/pmac/pmac_done.c b/core/lib/libtomcrypt/src/mac/pmac/pmac_done.c new file mode 100644 index 00000000000..49ce0e2756d --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/pmac/pmac_done.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file pmac_done.c + PMAC implementation, terminate a session, by Tom St Denis +*/ + +#ifdef LTC_PMAC + +int pmac_done(pmac_state *state, unsigned char *out, unsigned long *outlen) +{ + int err, x; + + LTC_ARGCHK(state != NULL); + LTC_ARGCHK(out != NULL); + if ((err = cipher_is_valid(state->cipher_idx)) != CRYPT_OK) { + return err; + } + + if ((state->buflen > (int)sizeof(state->block)) || (state->buflen < 0) || + (state->block_len > (int)sizeof(state->block)) || (state->buflen > state->block_len)) { + return CRYPT_INVALID_ARG; + } + + + /* handle padding. If multiple xor in L/x */ + + if (state->buflen == state->block_len) { + /* xor Lr against the checksum */ + for (x = 0; x < state->block_len; x++) { + state->checksum[x] ^= state->block[x] ^ state->Lr[x]; + } + } else { + /* otherwise xor message bytes then the 0x80 byte */ + for (x = 0; x < state->buflen; x++) { + state->checksum[x] ^= state->block[x]; + } + state->checksum[x] ^= 0x80; + } + + /* encrypt it */ + if ((err = cipher_descriptor[state->cipher_idx].ecb_encrypt(state->checksum, state->checksum, &state->key)) != CRYPT_OK) { + return err; + } + cipher_descriptor[state->cipher_idx].done(&state->key); + + /* store it */ + for (x = 0; x < state->block_len && x < (int)*outlen; x++) { + out[x] = state->checksum[x]; + } + *outlen = x; + +#ifdef LTC_CLEAN_STACK + zeromem(state, sizeof(*state)); +#endif + return CRYPT_OK; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/pmac/pmac_done.c,v $ */ +/* $Revision: 1.9 $ */ +/* $Date: 2006/12/28 01:27:23 $ */ diff --git a/core/lib/libtomcrypt/src/mac/pmac/pmac_file.c b/core/lib/libtomcrypt/src/mac/pmac/pmac_file.c new file mode 100644 index 00000000000..d0186925537 --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/pmac/pmac_file.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file pmac_file.c + PMAC implementation, process a file, by Tom St Denis +*/ + +#ifdef LTC_PMAC + +/** + PMAC a file + @param cipher The index of the cipher desired + @param key The secret key + @param keylen The length of the secret key (octets) + @param filename The name of the file to send through PMAC + @param out [out] Destination for the authentication tag + @param outlen [in/out] Max size and resulting size of the authentication tag + @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled +*/ +int pmac_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *filename, + unsigned char *out, unsigned long *outlen) +{ +#ifdef LTC_NO_FILE + return CRYPT_NOP; +#else + int err, x; + pmac_state pmac; + FILE *in; + unsigned char buf[512]; + + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(filename != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + in = fopen(filename, "rb"); + if (in == NULL) { + return CRYPT_FILE_NOTFOUND; + } + + if ((err = pmac_init(&pmac, cipher, key, keylen)) != CRYPT_OK) { + fclose(in); + return err; + } + + do { + x = fread(buf, 1, sizeof(buf), in); + if ((err = pmac_process(&pmac, buf, x)) != CRYPT_OK) { + fclose(in); + return err; + } + } while (x == sizeof(buf)); + fclose(in); + + if ((err = pmac_done(&pmac, out, outlen)) != CRYPT_OK) { + return err; + } + +#ifdef LTC_CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + + return CRYPT_OK; +#endif +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/pmac/pmac_file.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:23 $ */ diff --git a/core/lib/libtomcrypt/src/mac/pmac/pmac_init.c b/core/lib/libtomcrypt/src/mac/pmac/pmac_init.c new file mode 100644 index 00000000000..f0f386a1295 --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/pmac/pmac_init.c @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file pmac_init.c + PMAC implementation, initialize state, by Tom St Denis +*/ + +#ifdef LTC_PMAC + +static const struct { + int len; + unsigned char poly_div[MAXBLOCKSIZE], + poly_mul[MAXBLOCKSIZE]; +} polys[] = { +{ + 8, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B } +}, { + 16, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 } +} +}; + +/** + Initialize a PMAC state + @param pmac The PMAC state to initialize + @param cipher The index of the desired cipher + @param key The secret key + @param keylen The length of the secret key (octets) + @return CRYPT_OK if successful +*/ +int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen) +{ + int poly, x, y, m, err; + unsigned char *L; + + LTC_ARGCHK(pmac != NULL); + LTC_ARGCHK(key != NULL); + + /* valid cipher? */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + /* determine which polys to use */ + pmac->block_len = cipher_descriptor[cipher].block_length; + for (poly = 0; poly < (int)(sizeof(polys)/sizeof(polys[0])); poly++) { + if (polys[poly].len == pmac->block_len) { + break; + } + } + if (polys[poly].len != pmac->block_len) { + return CRYPT_INVALID_ARG; + } + +#ifdef LTC_FAST + if (pmac->block_len % sizeof(LTC_FAST_TYPE)) { + return CRYPT_INVALID_ARG; + } +#endif + + + /* schedule the key */ + if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &pmac->key)) != CRYPT_OK) { + return err; + } + + /* allocate L */ + L = XMALLOC(pmac->block_len); + if (L == NULL) { + return CRYPT_MEM; + } + + /* find L = E[0] */ + zeromem(L, pmac->block_len); + if ((err = cipher_descriptor[cipher].ecb_encrypt(L, L, &pmac->key)) != CRYPT_OK) { + goto error; + } + + /* find Ls[i] = L << i for i == 0..31 */ + XMEMCPY(pmac->Ls[0], L, pmac->block_len); + for (x = 1; x < 32; x++) { + m = pmac->Ls[x-1][0] >> 7; + for (y = 0; y < pmac->block_len-1; y++) { + pmac->Ls[x][y] = ((pmac->Ls[x-1][y] << 1) | (pmac->Ls[x-1][y+1] >> 7)) & 255; + } + pmac->Ls[x][pmac->block_len-1] = (pmac->Ls[x-1][pmac->block_len-1] << 1) & 255; + + if (m == 1) { + for (y = 0; y < pmac->block_len; y++) { + pmac->Ls[x][y] ^= polys[poly].poly_mul[y]; + } + } + } + + /* find Lr = L / x */ + m = L[pmac->block_len-1] & 1; + + /* shift right */ + for (x = pmac->block_len - 1; x > 0; x--) { + pmac->Lr[x] = ((L[x] >> 1) | (L[x-1] << 7)) & 255; + } + pmac->Lr[0] = L[0] >> 1; + + if (m == 1) { + for (x = 0; x < pmac->block_len; x++) { + pmac->Lr[x] ^= polys[poly].poly_div[x]; + } + } + + /* zero buffer, counters, etc... */ + pmac->block_index = 1; + pmac->cipher_idx = cipher; + pmac->buflen = 0; + zeromem(pmac->block, sizeof(pmac->block)); + zeromem(pmac->Li, sizeof(pmac->Li)); + zeromem(pmac->checksum, sizeof(pmac->checksum)); + err = CRYPT_OK; +error: +#ifdef LTC_CLEAN_STACK + zeromem(L, pmac->block_len); +#endif + + XFREE(L); + + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/pmac/pmac_init.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2006/12/28 01:27:23 $ */ diff --git a/core/lib/libtomcrypt/src/mac/pmac/pmac_memory.c b/core/lib/libtomcrypt/src/mac/pmac/pmac_memory.c new file mode 100644 index 00000000000..03073d8fd1d --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/pmac/pmac_memory.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file pmac_memory.c + PMAC implementation, process a block of memory, by Tom St Denis +*/ + +#ifdef LTC_PMAC + +/** + PMAC a block of memory + @param cipher The index of the cipher desired + @param key The secret key + @param keylen The length of the secret key (octets) + @param in The data you wish to send through PMAC + @param inlen The length of data you wish to send through PMAC (octets) + @param out [out] Destination for the authentication tag + @param outlen [in/out] The max size and resulting size of the authentication tag + @return CRYPT_OK if successful +*/ +int pmac_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + int err; + pmac_state *pmac; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* allocate ram for pmac state */ + pmac = XMALLOC(sizeof(pmac_state)); + if (pmac == NULL) { + return CRYPT_MEM; + } + + if ((err = pmac_init(pmac, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = pmac_process(pmac, in, inlen)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = pmac_done(pmac, out, outlen)) != CRYPT_OK) { + goto LBL_ERR; + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(pmac, sizeof(pmac_state)); +#endif + + XFREE(pmac); + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/pmac/pmac_memory.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:23 $ */ diff --git a/core/lib/libtomcrypt/src/mac/pmac/pmac_memory_multi.c b/core/lib/libtomcrypt/src/mac/pmac/pmac_memory_multi.c new file mode 100644 index 00000000000..28085ccde2a --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/pmac/pmac_memory_multi.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" +#include + +/** + @file pmac_memory_multi.c + PMAC implementation, process multiple blocks of memory, by Tom St Denis +*/ + +#ifdef LTC_PMAC + +/** + PMAC multiple blocks of memory + @param cipher The index of the cipher desired + @param key The secret key + @param keylen The length of the secret key (octets) + @param out [out] Destination for the authentication tag + @param outlen [in/out] The max size and resulting size of the authentication tag + @param in The data you wish to send through PMAC + @param inlen The length of data you wish to send through PMAC (octets) + @param ... tuples of (data,len) pairs to PMAC, terminated with a (NULL,x) (x=don't care) + @return CRYPT_OK if successful +*/ +int pmac_memory_multi(int cipher, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...) +{ + int err; + pmac_state *pmac; + va_list args; + const unsigned char *curptr; + unsigned long curlen; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* allocate ram for pmac state */ + pmac = XMALLOC(sizeof(pmac_state)); + if (pmac == NULL) { + return CRYPT_MEM; + } + + if ((err = pmac_init(pmac, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + va_start(args, inlen); + curptr = in; + curlen = inlen; + for (;;) { + /* process buf */ + if ((err = pmac_process(pmac, curptr, curlen)) != CRYPT_OK) { + goto LBL_ERR; + } + /* step to next */ + curptr = va_arg(args, const unsigned char*); + if (curptr == NULL) { + break; + } + curlen = va_arg(args, unsigned long); + } + if ((err = pmac_done(pmac, out, outlen)) != CRYPT_OK) { + goto LBL_ERR; + } +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(pmac, sizeof(pmac_state)); +#endif + XFREE(pmac); + va_end(args); + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/pmac/pmac_memory_multi.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:23 $ */ diff --git a/core/lib/libtomcrypt/src/mac/pmac/pmac_ntz.c b/core/lib/libtomcrypt/src/mac/pmac/pmac_ntz.c new file mode 100644 index 00000000000..cc9464e1a5f --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/pmac/pmac_ntz.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file pmac_ntz.c + PMAC implementation, internal function, by Tom St Denis +*/ + +#ifdef LTC_PMAC + +/** + Internal PMAC function +*/ +int pmac_ntz(unsigned long x) +{ + int c; + x &= 0xFFFFFFFFUL; + c = 0; + while ((x & 1) == 0) { + ++c; + x >>= 1; + } + return c; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/pmac/pmac_ntz.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:23 $ */ diff --git a/core/lib/libtomcrypt/src/mac/pmac/pmac_process.c b/core/lib/libtomcrypt/src/mac/pmac/pmac_process.c new file mode 100644 index 00000000000..beed309c0f4 --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/pmac/pmac_process.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file pmac_process.c + PMAC implementation, process data, by Tom St Denis +*/ + + +#ifdef LTC_PMAC + +/** + Process data in a PMAC stream + @param pmac The PMAC state + @param in The data to send through PMAC + @param inlen The length of the data to send through PMAC + @return CRYPT_OK if successful +*/ +int pmac_process(pmac_state *pmac, const unsigned char *in, unsigned long inlen) +{ + int err, n; + unsigned long x; + unsigned char Z[MAXBLOCKSIZE]; + + LTC_ARGCHK(pmac != NULL); + LTC_ARGCHK(in != NULL); + if ((err = cipher_is_valid(pmac->cipher_idx)) != CRYPT_OK) { + return err; + } + + if ((pmac->buflen > (int)sizeof(pmac->block)) || (pmac->buflen < 0) || + (pmac->block_len > (int)sizeof(pmac->block)) || (pmac->buflen > pmac->block_len)) { + return CRYPT_INVALID_ARG; + } + +#ifdef LTC_FAST + if (pmac->buflen == 0 && inlen > 16) { + unsigned long y; + for (x = 0; x < (inlen - 16); x += 16) { + pmac_shift_xor(pmac); + for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE*)(&Z[y])) = *((LTC_FAST_TYPE*)(&in[y])) ^ *((LTC_FAST_TYPE*)(&pmac->Li[y])); + } + if ((err = cipher_descriptor[pmac->cipher_idx].ecb_encrypt(Z, Z, &pmac->key)) != CRYPT_OK) { + return err; + } + for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE*)(&pmac->checksum[y])) ^= *((LTC_FAST_TYPE*)(&Z[y])); + } + in += 16; + } + inlen -= x; + } +#endif + + while (inlen != 0) { + /* ok if the block is full we xor in prev, encrypt and replace prev */ + if (pmac->buflen == pmac->block_len) { + pmac_shift_xor(pmac); + for (x = 0; x < (unsigned long)pmac->block_len; x++) { + Z[x] = pmac->Li[x] ^ pmac->block[x]; + } + if ((err = cipher_descriptor[pmac->cipher_idx].ecb_encrypt(Z, Z, &pmac->key)) != CRYPT_OK) { + return err; + } + for (x = 0; x < (unsigned long)pmac->block_len; x++) { + pmac->checksum[x] ^= Z[x]; + } + pmac->buflen = 0; + } + + /* add bytes */ + n = MIN(inlen, (unsigned long)(pmac->block_len - pmac->buflen)); + XMEMCPY(pmac->block + pmac->buflen, in, n); + pmac->buflen += n; + inlen -= n; + in += n; + } + +#ifdef LTC_CLEAN_STACK + zeromem(Z, sizeof(Z)); +#endif + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/pmac/pmac_process.c,v $ */ +/* $Revision: 1.9 $ */ +/* $Date: 2006/12/28 01:27:23 $ */ diff --git a/core/lib/libtomcrypt/src/mac/pmac/pmac_shift_xor.c b/core/lib/libtomcrypt/src/mac/pmac/pmac_shift_xor.c new file mode 100644 index 00000000000..53a8fcbd77c --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/pmac/pmac_shift_xor.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file pmac_shift_xor.c + PMAC implementation, internal function, by Tom St Denis +*/ + +#ifdef LTC_PMAC + +/** + Internal function. Performs the state update (adding correct multiple) + @param pmac The PMAC state. +*/ +void pmac_shift_xor(pmac_state *pmac) +{ + int x, y; + y = pmac_ntz(pmac->block_index++); +#ifdef LTC_FAST + for (x = 0; x < pmac->block_len; x += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE*)((unsigned char *)pmac->Li + x)) ^= + *((LTC_FAST_TYPE*)((unsigned char *)pmac->Ls[y] + x)); + } +#else + for (x = 0; x < pmac->block_len; x++) { + pmac->Li[x] ^= pmac->Ls[y][x]; + } +#endif +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/pmac/pmac_shift_xor.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:23 $ */ diff --git a/core/lib/libtomcrypt/src/mac/pmac/pmac_test.c b/core/lib/libtomcrypt/src/mac/pmac/pmac_test.c new file mode 100644 index 00000000000..1845e25c4b8 --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/pmac/pmac_test.c @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file pmac_test.c + PMAC implementation, self-test, by Tom St Denis +*/ + + +#ifdef LTC_PMAC + +/** + Test the LTC_OMAC implementation + @return CRYPT_OK if successful, CRYPT_NOP if testing has been disabled +*/ +int pmac_test(void) +{ +#if !defined(LTC_TEST) + return CRYPT_NOP; +#else + static const struct { + int msglen; + unsigned char key[16], msg[34], tag[16]; + } tests[] = { + + /* PMAC-AES-128-0B */ +{ + 0, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* msg */ + { 0x00 }, + /* tag */ + { 0x43, 0x99, 0x57, 0x2c, 0xd6, 0xea, 0x53, 0x41, + 0xb8, 0xd3, 0x58, 0x76, 0xa7, 0x09, 0x8a, 0xf7 } +}, + + /* PMAC-AES-128-3B */ +{ + 3, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* msg */ + { 0x00, 0x01, 0x02 }, + /* tag */ + { 0x25, 0x6b, 0xa5, 0x19, 0x3c, 0x1b, 0x99, 0x1b, + 0x4d, 0xf0, 0xc5, 0x1f, 0x38, 0x8a, 0x9e, 0x27 } +}, + + /* PMAC-AES-128-16B */ +{ + 16, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* msg */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* tag */ + { 0xeb, 0xbd, 0x82, 0x2f, 0xa4, 0x58, 0xda, 0xf6, + 0xdf, 0xda, 0xd7, 0xc2, 0x7d, 0xa7, 0x63, 0x38 } +}, + + /* PMAC-AES-128-20B */ +{ + 20, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* msg */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 }, + /* tag */ + { 0x04, 0x12, 0xca, 0x15, 0x0b, 0xbf, 0x79, 0x05, + 0x8d, 0x8c, 0x75, 0xa5, 0x8c, 0x99, 0x3f, 0x55 } +}, + + /* PMAC-AES-128-32B */ +{ + 32, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* msg */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, + /* tag */ + { 0xe9, 0x7a, 0xc0, 0x4e, 0x9e, 0x5e, 0x33, 0x99, + 0xce, 0x53, 0x55, 0xcd, 0x74, 0x07, 0xbc, 0x75 } +}, + + /* PMAC-AES-128-34B */ +{ + 34, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* msg */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21 }, + /* tag */ + { 0x5c, 0xba, 0x7d, 0x5e, 0xb2, 0x4f, 0x7c, 0x86, + 0xcc, 0xc5, 0x46, 0x04, 0xe5, 0x3d, 0x55, 0x12 } +} + +}; + int err, x, idx; + unsigned long len; + unsigned char outtag[MAXBLOCKSIZE]; + + /* AES can be under rijndael or aes... try to find it */ + if ((idx = find_cipher("aes")) == -1) { + if ((idx = find_cipher("rijndael")) == -1) { + return CRYPT_NOP; + } + } + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + len = sizeof(outtag); + if ((err = pmac_memory(idx, tests[x].key, 16, tests[x].msg, tests[x].msglen, outtag, &len)) != CRYPT_OK) { + return err; + } + + if (XMEMCMP(outtag, tests[x].tag, len)) { +#if 0 + unsigned long y; + printf("\nTAG:\n"); + for (y = 0; y < len; ) { + printf("0x%02x", outtag[y]); + if (y < len-1) printf(", "); + if (!(++y % 8)) printf("\n"); + } +#endif + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif /* LTC_TEST */ +} + +#endif /* PMAC_MODE */ + + + + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/pmac/pmac_test.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/core/lib/libtomcrypt/src/mac/pmac/sub.mk b/core/lib/libtomcrypt/src/mac/pmac/sub.mk new file mode 100644 index 00000000000..0146fded8bf --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/pmac/sub.mk @@ -0,0 +1,11 @@ +cflags-y += -Wno-unused-parameter + +srcs-y += pmac_done.c +srcs-y += pmac_file.c +srcs-y += pmac_init.c +srcs-y += pmac_memory.c +srcs-y += pmac_memory_multi.c +srcs-y += pmac_ntz.c +srcs-y += pmac_process.c +srcs-y += pmac_shift_xor.c +srcs-y += pmac_test.c diff --git a/core/lib/libtomcrypt/src/mac/sub.mk b/core/lib/libtomcrypt/src/mac/sub.mk new file mode 100644 index 00000000000..b9efc874e78 --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/sub.mk @@ -0,0 +1,4 @@ +subdirs-y += hmac +subdirs-y += omac +subdirs-y += pmac +subdirs-y += xcbc diff --git a/core/lib/libtomcrypt/src/mac/xcbc/sub.mk b/core/lib/libtomcrypt/src/mac/xcbc/sub.mk new file mode 100644 index 00000000000..7f66e423356 --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/xcbc/sub.mk @@ -0,0 +1,9 @@ +cflags-y += -Wno-unused-parameter + +srcs-y += xcbc_done.c +srcs-y += xcbc_file.c +srcs-y += xcbc_init.c +srcs-y += xcbc_memory.c +srcs-y += xcbc_memory_multi.c +srcs-y += xcbc_process.c +srcs-y += xcbc_test.c diff --git a/core/lib/libtomcrypt/src/mac/xcbc/xcbc_done.c b/core/lib/libtomcrypt/src/mac/xcbc/xcbc_done.c new file mode 100644 index 00000000000..34aa1992820 --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/xcbc/xcbc_done.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file xcbc_done.c + XCBC Support, terminate the state +*/ + +#ifdef LTC_XCBC + +/** Terminate the XCBC-MAC state + @param xcbc XCBC state to terminate + @param out [out] Destination for the MAC tag + @param outlen [in/out] Destination size and final tag size + Return CRYPT_OK on success +*/ +int xcbc_done(xcbc_state *xcbc, unsigned char *out, unsigned long *outlen) +{ + int err, x; + LTC_ARGCHK(xcbc != NULL); + LTC_ARGCHK(out != NULL); + + /* check structure */ + if ((err = cipher_is_valid(xcbc->cipher)) != CRYPT_OK) { + return err; + } + + if ((xcbc->blocksize > cipher_descriptor[xcbc->cipher].block_length) || (xcbc->blocksize < 0) || + (xcbc->buflen > xcbc->blocksize) || (xcbc->buflen < 0)) { + return CRYPT_INVALID_ARG; + } + + /* which key do we use? */ + if (xcbc->buflen == xcbc->blocksize) { + /* k2 */ + for (x = 0; x < xcbc->blocksize; x++) { + xcbc->IV[x] ^= xcbc->K[1][x]; + } + } else { + xcbc->IV[xcbc->buflen] ^= 0x80; + /* k3 */ + for (x = 0; x < xcbc->blocksize; x++) { + xcbc->IV[x] ^= xcbc->K[2][x]; + } + } + + /* encrypt */ + cipher_descriptor[xcbc->cipher].ecb_encrypt(xcbc->IV, xcbc->IV, &xcbc->key); + cipher_descriptor[xcbc->cipher].done(&xcbc->key); + + /* extract tag */ + for (x = 0; x < xcbc->blocksize && (unsigned long)x < *outlen; x++) { + out[x] = xcbc->IV[x]; + } + *outlen = x; + +#ifdef LTC_CLEAN_STACK + zeromem(xcbc, sizeof(*xcbc)); +#endif + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/xcbc/xcbc_done.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:27:23 $ */ + diff --git a/core/lib/libtomcrypt/src/mac/xcbc/xcbc_file.c b/core/lib/libtomcrypt/src/mac/xcbc/xcbc_file.c new file mode 100644 index 00000000000..fc790efbb4f --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/xcbc/xcbc_file.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file xcbc_file.c + XCBC support, process a file, Tom St Denis +*/ + +#ifdef LTC_XCBC + +/** + XCBC a file + @param cipher The index of the cipher desired + @param key The secret key + @param keylen The length of the secret key (octets) + @param filename The name of the file you wish to XCBC + @param out [out] Where the authentication tag is to be stored + @param outlen [in/out] The max size and resulting size of the authentication tag + @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled +*/ +int xcbc_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *filename, + unsigned char *out, unsigned long *outlen) +{ +#ifdef LTC_NO_FILE + return CRYPT_NOP; +#else + int err, x; + xcbc_state xcbc; + FILE *in; + unsigned char buf[512]; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(filename != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + in = fopen(filename, "rb"); + if (in == NULL) { + return CRYPT_FILE_NOTFOUND; + } + + if ((err = xcbc_init(&xcbc, cipher, key, keylen)) != CRYPT_OK) { + fclose(in); + return err; + } + + do { + x = fread(buf, 1, sizeof(buf), in); + if ((err = xcbc_process(&xcbc, buf, x)) != CRYPT_OK) { + fclose(in); + return err; + } + } while (x == sizeof(buf)); + fclose(in); + + if ((err = xcbc_done(&xcbc, out, outlen)) != CRYPT_OK) { + return err; + } + +#ifdef LTC_CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + + return CRYPT_OK; +#endif +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/xcbc/xcbc_file.c,v $ */ +/* $Revision: 1.2 $ */ +/* $Date: 2006/12/28 01:27:23 $ */ diff --git a/core/lib/libtomcrypt/src/mac/xcbc/xcbc_init.c b/core/lib/libtomcrypt/src/mac/xcbc/xcbc_init.c new file mode 100644 index 00000000000..14c63132e0f --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/xcbc/xcbc_init.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file xcbc_init.c + XCBC Support, start an XCBC state +*/ + +#ifdef LTC_XCBC + +/** Initialize XCBC-MAC state + @param xcbc [out] XCBC state to initialize + @param cipher Index of cipher to use + @param key [in] Secret key + @param keylen Length of secret key in octets + Return CRYPT_OK on success +*/ +int xcbc_init(xcbc_state *xcbc, int cipher, const unsigned char *key, unsigned long keylen) +{ + int x, y, err; + symmetric_key *skey; + unsigned long k1; + + LTC_ARGCHK(xcbc != NULL); + LTC_ARGCHK(key != NULL); + + /* schedule the key */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + +#ifdef LTC_FAST + if (cipher_descriptor[cipher].block_length % sizeof(LTC_FAST_TYPE)) { + return CRYPT_INVALID_ARG; + } +#endif + + skey = NULL; + + /* are we in pure XCBC mode with three keys? */ + if (keylen & LTC_XCBC_PURE) { + keylen &= ~LTC_XCBC_PURE; + + if (keylen < 2UL*cipher_descriptor[cipher].block_length) { + return CRYPT_INVALID_ARG; + } + + k1 = keylen - 2*cipher_descriptor[cipher].block_length; + XMEMCPY(xcbc->K[0], key, k1); + XMEMCPY(xcbc->K[1], key+k1, cipher_descriptor[cipher].block_length); + XMEMCPY(xcbc->K[2], key+k1 + cipher_descriptor[cipher].block_length, cipher_descriptor[cipher].block_length); + } else { + /* use the key expansion */ + k1 = cipher_descriptor[cipher].block_length; + + /* schedule the user key */ + skey = XCALLOC(1, sizeof(*skey)); + if (skey == NULL) { + return CRYPT_MEM; + } + + if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, skey)) != CRYPT_OK) { + goto done; + } + + /* make the three keys */ + for (y = 0; y < 3; y++) { + for (x = 0; x < cipher_descriptor[cipher].block_length; x++) { + xcbc->K[y][x] = y + 1; + } + cipher_descriptor[cipher].ecb_encrypt(xcbc->K[y], xcbc->K[y], skey); + } + } + + /* setup K1 */ + err = cipher_descriptor[cipher].setup(xcbc->K[0], k1, 0, &xcbc->key); + + /* setup struct */ + zeromem(xcbc->IV, cipher_descriptor[cipher].block_length); + xcbc->blocksize = cipher_descriptor[cipher].block_length; + xcbc->cipher = cipher; + xcbc->buflen = 0; +done: + cipher_descriptor[cipher].done(skey); + if (skey != NULL) { +#ifdef LTC_CLEAN_STACK + zeromem(skey, sizeof(*skey)); +#endif + XFREE(skey); + } + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/xcbc/xcbc_init.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/02/20 13:07:58 $ */ + diff --git a/core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory.c b/core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory.c new file mode 100644 index 00000000000..81783d266ed --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file xcbc_process.c + XCBC Support, XCBC-MAC a block of memory +*/ + +#ifdef LTC_XCBC + +/** XCBC-MAC a block of memory + @param cipher Index of cipher to use + @param key [in] Secret key + @param keylen Length of key in octets + @param in [in] Message to MAC + @param inlen Length of input in octets + @param out [out] Destination for the MAC tag + @param outlen [in/out] Output size and final tag size + Return CRYPT_OK on success. +*/ +int xcbc_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + xcbc_state *xcbc; + int err; + + /* is the cipher valid? */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + /* Use accelerator if found */ + if (cipher_descriptor[cipher].xcbc_memory != NULL) { + return cipher_descriptor[cipher].xcbc_memory(key, keylen, in, inlen, out, outlen); + } + + xcbc = XCALLOC(1, sizeof(*xcbc)); + if (xcbc == NULL) { + return CRYPT_MEM; + } + + if ((err = xcbc_init(xcbc, cipher, key, keylen)) != CRYPT_OK) { + goto done; + } + + if ((err = xcbc_process(xcbc, in, inlen)) != CRYPT_OK) { + goto done; + } + + err = xcbc_done(xcbc, out, outlen); +done: + XFREE(xcbc); + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/xcbc/xcbc_memory.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:27:23 $ */ diff --git a/core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory_multi.c b/core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory_multi.c new file mode 100644 index 00000000000..8c5ded4cfac --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory_multi.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" +#include + +/** + @file xcbc_memory_multi.c + XCBC support, process multiple blocks of memory, Tom St Denis +*/ + +#ifdef LTC_XCBC + +/** + XCBC multiple blocks of memory + @param cipher The index of the desired cipher + @param key The secret key + @param keylen The length of the secret key (octets) + @param out [out] The destination of the authentication tag + @param outlen [in/out] The max size and resulting size of the authentication tag (octets) + @param in The data to send through XCBC + @param inlen The length of the data to send through XCBC (octets) + @param ... tuples of (data,len) pairs to XCBC, terminated with a (NULL,x) (x=don't care) + @return CRYPT_OK if successful +*/ +int xcbc_memory_multi(int cipher, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...) +{ + int err; + xcbc_state *xcbc; + va_list args; + const unsigned char *curptr; + unsigned long curlen; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* allocate ram for xcbc state */ + xcbc = XMALLOC(sizeof(xcbc_state)); + if (xcbc == NULL) { + return CRYPT_MEM; + } + + /* xcbc process the message */ + if ((err = xcbc_init(xcbc, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + va_start(args, inlen); + curptr = in; + curlen = inlen; + for (;;) { + /* process buf */ + if ((err = xcbc_process(xcbc, curptr, curlen)) != CRYPT_OK) { + goto LBL_ERR; + } + /* step to next */ + curptr = va_arg(args, const unsigned char*); + if (curptr == NULL) { + break; + } + curlen = va_arg(args, unsigned long); + } + if ((err = xcbc_done(xcbc, out, outlen)) != CRYPT_OK) { + goto LBL_ERR; + } +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(xcbc, sizeof(xcbc_state)); +#endif + XFREE(xcbc); + va_end(args); + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/xcbc/xcbc_memory_multi.c,v $ */ +/* $Revision: 1.2 $ */ +/* $Date: 2006/12/28 01:27:23 $ */ diff --git a/core/lib/libtomcrypt/src/mac/xcbc/xcbc_process.c b/core/lib/libtomcrypt/src/mac/xcbc/xcbc_process.c new file mode 100644 index 00000000000..63f6d5ff734 --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/xcbc/xcbc_process.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file xcbc_process.c + XCBC Support, process blocks with XCBC +*/ + +#ifdef LTC_XCBC + +/** Process data through XCBC-MAC + @param xcbc The XCBC-MAC state + @param in Input data to process + @param inlen Length of input in octets + Return CRYPT_OK on success +*/ +int xcbc_process(xcbc_state *xcbc, const unsigned char *in, unsigned long inlen) +{ + int err; +#ifdef LTC_FAST + int x; +#endif + + LTC_ARGCHK(xcbc != NULL); + LTC_ARGCHK(in != NULL); + + /* check structure */ + if ((err = cipher_is_valid(xcbc->cipher)) != CRYPT_OK) { + return err; + } + + if ((xcbc->blocksize > cipher_descriptor[xcbc->cipher].block_length) || (xcbc->blocksize < 0) || + (xcbc->buflen > xcbc->blocksize) || (xcbc->buflen < 0)) { + return CRYPT_INVALID_ARG; + } + +#ifdef LTC_FAST + if (xcbc->buflen == 0) { + while (inlen > (unsigned long)xcbc->blocksize) { + for (x = 0; x < xcbc->blocksize; x += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE*)&(xcbc->IV[x])) ^= *((LTC_FAST_TYPE*)&(in[x])); + } + cipher_descriptor[xcbc->cipher].ecb_encrypt(xcbc->IV, xcbc->IV, &xcbc->key); + in += xcbc->blocksize; + inlen -= xcbc->blocksize; + } + } +#endif + + while (inlen) { + if (xcbc->buflen == xcbc->blocksize) { + cipher_descriptor[xcbc->cipher].ecb_encrypt(xcbc->IV, xcbc->IV, &xcbc->key); + xcbc->buflen = 0; + } + xcbc->IV[xcbc->buflen++] ^= *in++; + --inlen; + } + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/xcbc/xcbc_process.c,v $ */ +/* $Revision: 1.10 $ */ +/* $Date: 2006/12/28 01:27:23 $ */ + diff --git a/core/lib/libtomcrypt/src/mac/xcbc/xcbc_test.c b/core/lib/libtomcrypt/src/mac/xcbc/xcbc_test.c new file mode 100644 index 00000000000..976f9370b17 --- /dev/null +++ b/core/lib/libtomcrypt/src/mac/xcbc/xcbc_test.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file xcbc_test.c + XCBC Support, Test XCBC-MAC mode +*/ + +#ifdef LTC_XCBC + +/** Test XCBC-MAC mode + Return CRYPT_OK on succes +*/ +int xcbc_test(void) +{ +#ifdef LTC_NO_TEST + return CRYPT_NOP; +#else + static const struct { + int msglen; + unsigned char K[16], M[34], T[16]; + } tests[] = { +{ + 0, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + + { 0 }, + + { 0x75, 0xf0, 0x25, 0x1d, 0x52, 0x8a, 0xc0, 0x1c, + 0x45, 0x73, 0xdf, 0xd5, 0x84, 0xd7, 0x9f, 0x29 } +}, + +{ + 3, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + + { 0x00, 0x01, 0x02 }, + + { 0x5b, 0x37, 0x65, 0x80, 0xae, 0x2f, 0x19, 0xaf, + 0xe7, 0x21, 0x9c, 0xee, 0xf1, 0x72, 0x75, 0x6f } +}, + +{ + 16, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + + { 0xd2, 0xa2, 0x46, 0xfa, 0x34, 0x9b, 0x68, 0xa7, + 0x99, 0x98, 0xa4, 0x39, 0x4f, 0xf7, 0xa2, 0x63 } +}, + +{ + 32, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, + + { 0xf5, 0x4f, 0x0e, 0xc8, 0xd2, 0xb9, 0xf3, 0xd3, + 0x68, 0x07, 0x73, 0x4b, 0xd5, 0x28, 0x3f, 0xd4 } +}, + +{ + 34, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21 }, + + { 0xbe, 0xcb, 0xb3, 0xbc, 0xcd, 0xb5, 0x18, 0xa3, + 0x06, 0x77, 0xd5, 0x48, 0x1f, 0xb6, 0xb4, 0xd8 }, +}, + + + +}; + unsigned char T[16]; + unsigned long taglen; + int err, x, idx; + + /* AES can be under rijndael or aes... try to find it */ + if ((idx = find_cipher("aes")) == -1) { + if ((idx = find_cipher("rijndael")) == -1) { + return CRYPT_NOP; + } + } + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + taglen = 16; + if ((err = xcbc_memory(idx, tests[x].K, 16, tests[x].M, tests[x].msglen, T, &taglen)) != CRYPT_OK) { + return err; + } + if (taglen != 16 || XMEMCMP(T, tests[x].T, 16)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + + return CRYPT_OK; +#endif +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/xcbc/xcbc_test.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:23 $ */ + diff --git a/core/lib/libtomcrypt/src/math/multi.c b/core/lib/libtomcrypt/src/math/multi.c new file mode 100644 index 00000000000..82fb6fd7100 --- /dev/null +++ b/core/lib/libtomcrypt/src/math/multi.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +#ifdef MPI +#include + +int ltc_init_multi(void **a, ...) +{ + void **cur = a; + int np = 0; + va_list args; + + va_start(args, a); + while (cur != NULL) { + if (mp_init(cur) != CRYPT_OK) { + /* failed */ + va_list clean_list; + + va_start(clean_list, a); + cur = a; + while (np--) { + mp_clear(*cur); + cur = va_arg(clean_list, void**); + } + va_end(clean_list); + return CRYPT_MEM; + } + ++np; + cur = va_arg(args, void**); + } + va_end(args); + return CRYPT_OK; +} + +void ltc_deinit_multi(void *a, ...) +{ + void *cur = a; + va_list args; + + va_start(args, a); + while (cur != NULL) { + mp_clear(cur); + cur = va_arg(args, void *); + } + va_end(args); +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/math/multi.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:23 $ */ diff --git a/core/lib/libtomcrypt/src/math/rand_prime.c b/core/lib/libtomcrypt/src/math/rand_prime.c new file mode 100644 index 00000000000..a23d27d72fa --- /dev/null +++ b/core/lib/libtomcrypt/src/math/rand_prime.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file rand_prime.c + Generate a random prime, Tom St Denis +*/ + +#define USE_BBS 1 + +int rand_prime(void *N, long len, prng_state *prng, int wprng) +{ + int err, res, type; + unsigned char *buf; + + LTC_ARGCHK(N != NULL); + + /* get type */ + if (len < 0) { + type = USE_BBS; + len = -len; + } else { + type = 0; + } + + /* allow sizes between 2 and 512 bytes for a prime size */ + if (len < 2 || len > 512) { + return CRYPT_INVALID_PRIME_SIZE; + } + + /* valid PRNG? Better be! */ + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + /* allocate buffer to work with */ + buf = XCALLOC(1, len); + if (buf == NULL) { + return CRYPT_MEM; + } + + do { + /* generate value */ + if (prng_descriptor[wprng].read(buf, len, prng) != (unsigned long)len) { + XFREE(buf); + return CRYPT_ERROR_READPRNG; + } + + /* munge bits */ + buf[0] |= 0x80 | 0x40; + buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00); + + /* load value */ + if ((err = mp_read_unsigned_bin(N, buf, len)) != CRYPT_OK) { + XFREE(buf); + return err; + } + + /* test */ + if ((err = mp_prime_is_prime(N, 8, &res)) != CRYPT_OK) { + XFREE(buf); + return err; + } + } while (res == LTC_MP_NO); + +#ifdef LTC_CLEAN_STACK + zeromem(buf, len); +#endif + + XFREE(buf); + return CRYPT_OK; +} + + + +/* $Source: /cvs/libtom/libtomcrypt/src/math/rand_prime.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:23 $ */ diff --git a/core/lib/libtomcrypt/src/math/sub.mk b/core/lib/libtomcrypt/src/math/sub.mk new file mode 100644 index 00000000000..85850be6f33 --- /dev/null +++ b/core/lib/libtomcrypt/src/math/sub.mk @@ -0,0 +1,2 @@ +srcs-y += multi.c +srcs-y += rand_prime.c diff --git a/core/lib/libtomcrypt/src/misc/base64/base64_decode.c b/core/lib/libtomcrypt/src/misc/base64/base64_decode.c new file mode 100644 index 00000000000..a105f5a0172 --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/base64/base64_decode.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file base64_decode.c + Compliant base64 code donated by Wayne Scott (wscott@bitmover.com) +*/ + + +#ifdef LTC_BASE64 + +static const unsigned char map[256] = { +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, +255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, +255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255 }; + +/** + base64 decode a block of memory + @param in The base64 data to decode + @param inlen The length of the base64 data + @param out [out] The destination of the binary decoded data + @param outlen [in/out] The max size and resulting size of the decoded data + @return CRYPT_OK if successful +*/ +int base64_decode(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long t, x, y, z; + unsigned char c; + int g; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + g = 3; + for (x = y = z = t = 0; x < inlen; x++) { + c = map[in[x]&0xFF]; + if (c == 255) continue; + /* the final = symbols are read and used to trim the remaining bytes */ + if (c == 254) { + c = 0; + /* prevent g < 0 which would potentially allow an overflow later */ + if (--g < 0) { + return CRYPT_INVALID_PACKET; + } + } else if (g != 3) { + /* we only allow = to be at the end */ + return CRYPT_INVALID_PACKET; + } + + t = (t<<6)|c; + + if (++y == 4) { + if (z + g > *outlen) { + return CRYPT_BUFFER_OVERFLOW; + } + out[z++] = (unsigned char)((t>>16)&255); + if (g > 1) out[z++] = (unsigned char)((t>>8)&255); + if (g > 2) out[z++] = (unsigned char)(t&255); + y = t = 0; + } + } + if (y != 0) { + return CRYPT_INVALID_PACKET; + } + *outlen = z; + return CRYPT_OK; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/base64/base64_decode.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/misc/base64/base64_encode.c b/core/lib/libtomcrypt/src/misc/base64/base64_encode.c new file mode 100644 index 00000000000..428034209ad --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/base64/base64_encode.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file base64_encode.c + Compliant base64 encoder donated by Wayne Scott (wscott@bitmover.com) +*/ + + +#ifdef LTC_BASE64 + +static const char *codes = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/** + base64 Encode a buffer (NUL terminated) + @param in The input buffer to encode + @param inlen The length of the input buffer + @param out [out] The destination of the base64 encoded data + @param outlen [in/out] The max size and resulting size + @return CRYPT_OK if successful +*/ +int base64_encode(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long i, len2, leven; + unsigned char *p; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* valid output size ? */ + len2 = 4 * ((inlen + 2) / 3); + if (*outlen < len2 + 1) { + *outlen = len2 + 1; + return CRYPT_BUFFER_OVERFLOW; + } + p = out; + leven = 3*(inlen / 3); + for (i = 0; i < leven; i += 3) { + *p++ = codes[(in[0] >> 2) & 0x3F]; + *p++ = codes[(((in[0] & 3) << 4) + (in[1] >> 4)) & 0x3F]; + *p++ = codes[(((in[1] & 0xf) << 2) + (in[2] >> 6)) & 0x3F]; + *p++ = codes[in[2] & 0x3F]; + in += 3; + } + /* Pad it if necessary... */ + if (i < inlen) { + unsigned a = in[0]; + unsigned b = (i+1 < inlen) ? in[1] : 0; + + *p++ = codes[(a >> 2) & 0x3F]; + *p++ = codes[(((a & 3) << 4) + (b >> 4)) & 0x3F]; + *p++ = (i+1 < inlen) ? codes[(((b & 0xf) << 2)) & 0x3F] : '='; + *p++ = '='; + } + + /* append a NULL byte */ + *p = '\0'; + + /* return ok */ + *outlen = p - out; + return CRYPT_OK; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/base64/base64_encode.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/misc/base64/sub.mk b/core/lib/libtomcrypt/src/misc/base64/sub.mk new file mode 100644 index 00000000000..91916905a57 --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/base64/sub.mk @@ -0,0 +1,2 @@ +srcs-y += base64_decode.c +srcs-y += base64_encode.c diff --git a/core/lib/libtomcrypt/src/misc/burn_stack.c b/core/lib/libtomcrypt/src/misc/burn_stack.c new file mode 100644 index 00000000000..8b903d4e498 --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/burn_stack.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file burn_stack.c + Burn stack, Tom St Denis +*/ + +/** + Burn some stack memory + @param len amount of stack to burn in bytes +*/ +void burn_stack(unsigned long len) +{ + unsigned char buf[32]; + zeromem(buf, sizeof(buf)); + if (len > (unsigned long)sizeof(buf)) + burn_stack(len - sizeof(buf)); +} + + + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/burn_stack.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt.c b/core/lib/libtomcrypt/src/misc/crypt/crypt.c new file mode 100644 index 00000000000..e66a085051a --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/crypt/crypt.c @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file crypt.c + Build strings, Tom St Denis +*/ + +const char *crypt_build_settings = + "LibTomCrypt " SCRYPT " (Tom St Denis, tomstdenis@gmail.com)\n" + "LibTomCrypt is public domain software.\n" + "Built on " __DATE__ " at " __TIME__ "\n\n\n" + "Endianess: " +#if defined(ENDIAN_NEUTRAL) + "neutral\n" +#elif defined(ENDIAN_LITTLE) + "little" + #if defined(ENDIAN_32BITWORD) + " (32-bit words)\n" + #else + " (64-bit words)\n" + #endif +#elif defined(ENDIAN_BIG) + "big" + #if defined(ENDIAN_32BITWORD) + " (32-bit words)\n" + #else + " (64-bit words)\n" + #endif +#endif + "Clean stack: " +#if defined(LTC_CLEAN_STACK) + "enabled\n" +#else + "disabled\n" +#endif + "Ciphers built-in:\n" +#if defined(LTC_BLOWFISH) + " Blowfish\n" +#endif +#if defined(LTC_RC2) + " LTC_RC2\n" +#endif +#if defined(LTC_RC5) + " LTC_RC5\n" +#endif +#if defined(LTC_RC6) + " LTC_RC6\n" +#endif +#if defined(LTC_SAFERP) + " Safer+\n" +#endif +#if defined(LTC_SAFER) + " Safer\n" +#endif +#if defined(LTC_RIJNDAEL) + " Rijndael\n" +#endif +#if defined(LTC_XTEA) + " LTC_XTEA\n" +#endif +#if defined(LTC_TWOFISH) + " Twofish " + #if defined(LTC_TWOFISH_SMALL) && defined(LTC_TWOFISH_TABLES) && defined(LTC_TWOFISH_ALL_TABLES) + "(small, tables, all_tables)\n" + #elif defined(LTC_TWOFISH_SMALL) && defined(LTC_TWOFISH_TABLES) + "(small, tables)\n" + #elif defined(LTC_TWOFISH_SMALL) && defined(LTC_TWOFISH_ALL_TABLES) + "(small, all_tables)\n" + #elif defined(LTC_TWOFISH_TABLES) && defined(LTC_TWOFISH_ALL_TABLES) + "(tables, all_tables)\n" + #elif defined(LTC_TWOFISH_SMALL) + "(small)\n" + #elif defined(LTC_TWOFISH_TABLES) + "(tables)\n" + #elif defined(LTC_TWOFISH_ALL_TABLES) + "(all_tables)\n" + #else + "\n" + #endif +#endif +#if defined(LTC_DES) + " LTC_DES\n" +#endif +#if defined(LTC_CAST5) + " LTC_CAST5\n" +#endif +#if defined(LTC_NOEKEON) + " Noekeon\n" +#endif +#if defined(LTC_SKIPJACK) + " Skipjack\n" +#endif +#if defined(LTC_KHAZAD) + " Khazad\n" +#endif +#if defined(LTC_ANUBIS) + " Anubis " +#endif +#if defined(LTC_ANUBIS_TWEAK) + " (tweaked)" +#endif + "\n" +#if defined(LTC_KSEED) + " LTC_KSEED\n" +#endif +#if defined(LTC_KASUMI) + " KASUMI\n" +#endif + + "\nHashes built-in:\n" +#if defined(LTC_SHA512) + " LTC_SHA-512\n" +#endif +#if defined(LTC_SHA384) + " LTC_SHA-384\n" +#endif +#if defined(LTC_SHA256) + " LTC_SHA-256\n" +#endif +#if defined(LTC_SHA224) + " LTC_SHA-224\n" +#endif +#if defined(LTC_TIGER) + " LTC_TIGER\n" +#endif +#if defined(LTC_SHA1) + " LTC_SHA1\n" +#endif +#if defined(LTC_MD5) + " LTC_MD5\n" +#endif +#if defined(LTC_MD4) + " LTC_MD4\n" +#endif +#if defined(LTC_MD2) + " LTC_MD2\n" +#endif +#if defined(LTC_RIPEMD128) + " LTC_RIPEMD128\n" +#endif +#if defined(LTC_RIPEMD160) + " LTC_RIPEMD160\n" +#endif +#if defined(LTC_RIPEMD256) + " LTC_RIPEMD256\n" +#endif +#if defined(LTC_RIPEMD320) + " LTC_RIPEMD320\n" +#endif +#if defined(LTC_WHIRLPOOL) + " LTC_WHIRLPOOL\n" +#endif +#if defined(LTC_CHC_HASH) + " LTC_CHC_HASH \n" +#endif + + "\nBlock Chaining Modes:\n" +#if defined(LTC_CFB_MODE) + " CFB\n" +#endif +#if defined(LTC_OFB_MODE) + " OFB\n" +#endif +#if defined(LTC_ECB_MODE) + " ECB\n" +#endif +#if defined(LTC_CBC_MODE) + " CBC\n" +#endif +#if defined(LTC_CTR_MODE) + " CTR " +#endif +#if defined(LTC_CTR_OLD) + " (CTR_OLD) " +#endif + "\n" +#if defined(LRW_MODE) + " LRW_MODE" +#if defined(LRW_TABLES) + " (LRW_TABLES) " +#endif + "\n" +#endif +#if defined(LTC_F8_MODE) + " F8 MODE\n" +#endif +#if defined(LTC_XTS_MODE) + " LTC_XTS_MODE\n" +#endif + + "\nMACs:\n" +#if defined(LTC_HMAC) + " LTC_HMAC\n" +#endif +#if defined(LTC_OMAC) + " LTC_OMAC\n" +#endif +#if defined(LTC_PMAC) + " PMAC\n" +#endif +#if defined(LTC_PELICAN) + " LTC_PELICAN\n" +#endif +#if defined(LTC_XCBC) + " XCBC-MAC\n" +#endif +#if defined(LTC_F9_MODE) + " F9-MAC\n" +#endif + + "\nENC + AUTH modes:\n" +#if defined(LTC_EAX_MODE) + " LTC_EAX_MODE\n" +#endif +#if defined(LTC_OCB_MODE) + " LTC_OCB_MODE\n" +#endif +#if defined(LTC_CCM_MODE) + " LTC_CCM_MODE\n" +#endif +#if defined(LTC_GCM_MODE) + " LTC_GCM_MODE " +#endif +#if defined(LTC_GCM_TABLES) + " (LTC_GCM_TABLES) " +#endif + "\n" + + "\nPRNG:\n" +#if defined(LTC_YARROW) + " Yarrow\n" +#endif +#if defined(LTC_SPRNG) + " LTC_SPRNG\n" +#endif +#if defined(LTC_RC4) + " LTC_RC4\n" +#endif +#if defined(LTC_FORTUNA) + " Fortuna\n" +#endif +#if defined(LTC_SOBER128) + " LTC_SOBER128\n" +#endif + + "\nPK Algs:\n" +#if defined(LTC_MRSA) + " RSA \n" +#endif +#if defined(LTC_MECC) + " ECC\n" +#endif +#if defined(LTC_MDSA) + " DSA\n" +#endif +#if defined(MKAT) + " Katja\n" +#endif + + "\nCompiler:\n" +#if defined(WIN32) + " WIN32 platform detected.\n" +#endif +#if defined(__CYGWIN__) + " CYGWIN Detected.\n" +#endif +#if defined(__DJGPP__) + " DJGPP Detected.\n" +#endif +#if defined(_MSC_VER) + " MSVC compiler detected.\n" +#endif +#if defined(__GNUC__) + " GCC compiler detected.\n" +#endif +#if defined(INTEL_CC) + " Intel C Compiler detected.\n" +#endif +#if defined(__x86_64__) + " x86-64 detected.\n" +#endif +#if defined(LTC_PPC32) + " LTC_PPC32 defined \n" +#endif + + "\nVarious others: " +#if defined(LTC_BASE64) + " LTC_BASE64 " +#endif +#if defined(MPI) + " MPI " +#endif +#if defined(TRY_UNRANDOM_FIRST) + " TRY_UNRANDOM_FIRST " +#endif +#if defined(LTC_TEST) + " LTC_TEST " +#endif +#if defined(LTC_PKCS_1) + " LTC_PKCS#1 " +#endif +#if defined(LTC_PKCS_5) + " LTC_PKCS#5 " +#endif +#if defined(LTC_SMALL_CODE) + " LTC_SMALL_CODE " +#endif +#if defined(LTC_NO_FILE) + " LTC_NO_FILE " +#endif +#if defined(LTC_DER) + " LTC_DER " +#endif +#if defined(LTC_FAST) + " LTC_FAST " +#endif +#if defined(LTC_NO_FAST) + " LTC_NO_FAST " +#endif +#if defined(LTC_NO_BSWAP) + " LTC_NO_BSWAP " +#endif +#if defined(LTC_NO_ASM) + " LTC_NO_ASM " +#endif +#if defined(LTC_NO_TEST) + " LTC_NO_TEST " +#endif +#if defined(LTC_NO_TABLES) + " LTC_NO_TABLES " +#endif +#if defined(LTC_PTHREAD) + " LTC_PTHREAD " +#endif +#if defined(LTM_LTC_DESC) + " LTM_DESC " +#endif +#if defined(TFM_LTC_DESC) + " TFM_DESC " +#endif +#if defined(LTC_MECC_ACCEL) + " LTC_MECC_ACCEL " +#endif +#if defined(GMP_LTC_DESC) + " GMP_DESC " +#endif +#if defined(LTC_EASY) + " (easy) " +#endif +#if defined(LTC_MECC_FP) + " LTC_MECC_FP " +#endif +#if defined(LTC_ECC_SHAMIR) + " LTC_ECC_SHAMIR " +#endif + "\n" + "\n\n\n" + ; + + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt.c,v $ */ +/* $Revision: 1.36 $ */ +/* $Date: 2007/05/12 14:46:12 $ */ diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt_argchk.c b/core/lib/libtomcrypt/src/misc/crypt/crypt_argchk.c new file mode 100644 index 00000000000..2f1d3a7f7a8 --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/crypt/crypt_argchk.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" +#include + +/** + @file crypt_argchk.c + Perform argument checking, Tom St Denis +*/ + +#if (ARGTYPE == 0) +void crypt_argchk(const char *v, const char *s, int d) +{ + fprintf(stderr, "LTC_ARGCHK '%s' failure on line %d of file %s\n", + v, d, s); + (void)raise(SIGABRT); +} +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_argchk.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_descriptor.c b/core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_descriptor.c new file mode 100644 index 00000000000..7f39c8a589c --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_descriptor.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file crypt_cipher_descriptor.c + Stores the cipher descriptor table, Tom St Denis +*/ + +struct ltc_cipher_descriptor cipher_descriptor[TAB_SIZE] = { +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } + }; + +LTC_MUTEX_GLOBAL(ltc_cipher_mutex) + + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_cipher_descriptor.c,v $ */ +/* $Revision: 1.13 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_is_valid.c b/core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_is_valid.c new file mode 100644 index 00000000000..2fe490f878c --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_is_valid.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file crypt_cipher_is_valid.c + Determine if cipher is valid, Tom St Denis +*/ + +/* + Test if a cipher index is valid + @param idx The index of the cipher to search for + @return CRYPT_OK if valid +*/ +int cipher_is_valid(int idx) +{ + LTC_MUTEX_LOCK(<c_cipher_mutex); + if (idx < 0 || idx >= TAB_SIZE || cipher_descriptor[idx].name == NULL) { + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return CRYPT_INVALID_CIPHER; + } + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return CRYPT_OK; +} + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_cipher_is_valid.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher.c b/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher.c new file mode 100644 index 00000000000..f712fb469b3 --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file crypt_find_cipher.c + Find a cipher in the descriptor tables, Tom St Denis +*/ + +/** + Find a registered cipher by name + @param name The name of the cipher to look for + @return >= 0 if found, -1 if not present +*/ +int find_cipher(const char *name) +{ + int x; + LTC_ARGCHK(name != NULL); + LTC_MUTEX_LOCK(<c_cipher_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (cipher_descriptor[x].name != NULL && !XSTRCMP(cipher_descriptor[x].name, name)) { + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return x; + } + } + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return -1; +} + + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_find_cipher.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_any.c b/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_any.c new file mode 100644 index 00000000000..87237629353 --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_any.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file crypt_find_cipher_any.c + Find a cipher in the descriptor tables, Tom St Denis +*/ + +/** + Find a cipher flexibly. First by name then if not present by block and key size + @param name The name of the cipher desired + @param blocklen The minimum length of the block cipher desired (octets) + @param keylen The minimum length of the key size desired (octets) + @return >= 0 if found, -1 if not present +*/ +int find_cipher_any(const char *name, int blocklen, int keylen) +{ + int x; + + LTC_ARGCHK(name != NULL); + + x = find_cipher(name); + if (x != -1) return x; + + LTC_MUTEX_LOCK(<c_cipher_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (cipher_descriptor[x].name == NULL) { + continue; + } + if (blocklen <= (int)cipher_descriptor[x].block_length && keylen <= (int)cipher_descriptor[x].max_key_length) { + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return x; + } + } + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return -1; +} + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_find_cipher_any.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_id.c b/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_id.c new file mode 100644 index 00000000000..a9ee47661f9 --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_id.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file crypt_find_cipher_id.c + Find cipher by ID, Tom St Denis +*/ + +/** + Find a cipher by ID number + @param ID The ID (not same as index) of the cipher to find + @return >= 0 if found, -1 if not present +*/ +int find_cipher_id(unsigned char ID) +{ + int x; + LTC_MUTEX_LOCK(<c_cipher_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (cipher_descriptor[x].ID == ID) { + x = (cipher_descriptor[x].name == NULL) ? -1 : x; + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return x; + } + } + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return -1; +} + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_find_cipher_id.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash.c b/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash.c new file mode 100644 index 00000000000..02dbb00e686 --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file crypt_find_hash.c + Find a hash, Tom St Denis +*/ + +/** + Find a registered hash by name + @param name The name of the hash to look for + @return >= 0 if found, -1 if not present +*/ +int find_hash(const char *name) +{ + int x; + LTC_ARGCHK(name != NULL); + LTC_MUTEX_LOCK(<c_hash_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (hash_descriptor[x].name != NULL && XSTRCMP(hash_descriptor[x].name, name) == 0) { + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return x; + } + } + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return -1; +} + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_find_hash.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_any.c b/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_any.c new file mode 100644 index 00000000000..16c3c1e695c --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_any.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file crypt_find_hash_any.c + Find a hash, Tom St Denis +*/ + +/** + Find a hash flexibly. First by name then if not present by digest size + @param name The name of the hash desired + @param digestlen The minimum length of the digest size (octets) + @return >= 0 if found, -1 if not present +*/int find_hash_any(const char *name, int digestlen) +{ + int x, y, z; + LTC_ARGCHK(name != NULL); + + x = find_hash(name); + if (x != -1) return x; + + LTC_MUTEX_LOCK(<c_hash_mutex); + y = MAXBLOCKSIZE+1; + z = -1; + for (x = 0; x < TAB_SIZE; x++) { + if (hash_descriptor[x].name == NULL) { + continue; + } + if ((int)hash_descriptor[x].hashsize >= digestlen && (int)hash_descriptor[x].hashsize < y) { + z = x; + y = hash_descriptor[x].hashsize; + } + } + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return z; +} + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_find_hash_any.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_id.c b/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_id.c new file mode 100644 index 00000000000..9f039aaad98 --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_id.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file crypt_find_hash_id.c + Find hash by ID, Tom St Denis +*/ + +/** + Find a hash by ID number + @param ID The ID (not same as index) of the hash to find + @return >= 0 if found, -1 if not present +*/ +int find_hash_id(unsigned char ID) +{ + int x; + LTC_MUTEX_LOCK(<c_hash_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (hash_descriptor[x].ID == ID) { + x = (hash_descriptor[x].name == NULL) ? -1 : x; + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return x; + } + } + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return -1; +} + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_find_hash_id.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_oid.c b/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_oid.c new file mode 100644 index 00000000000..83e5f84ab52 --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_oid.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file crypt_find_hash_oid.c + Find a hash, Tom St Denis +*/ + +int find_hash_oid(const unsigned long *ID, unsigned long IDlen) +{ + int x; + LTC_ARGCHK(ID != NULL); + LTC_MUTEX_LOCK(<c_hash_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (hash_descriptor[x].name != NULL && hash_descriptor[x].OIDlen == IDlen && !XMEMCMP(hash_descriptor[x].OID, ID, sizeof(unsigned long) * IDlen)) { + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return x; + } + } + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return -1; +} + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_find_hash_oid.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt_find_prng.c b/core/lib/libtomcrypt/src/misc/crypt/crypt_find_prng.c new file mode 100644 index 00000000000..fe05752a0ef --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/crypt/crypt_find_prng.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file crypt_find_prng.c + Find a PRNG, Tom St Denis +*/ + +/** + Find a registered PRNG by name + @param name The name of the PRNG to look for + @return >= 0 if found, -1 if not present +*/ +int find_prng(const char *name) +{ + int x; + LTC_ARGCHK(name != NULL); + LTC_MUTEX_LOCK(<c_prng_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if ((prng_descriptor[x].name != NULL) && XSTRCMP(prng_descriptor[x].name, name) == 0) { + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return x; + } + } + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return -1; +} + + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_find_prng.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt_fsa.c b/core/lib/libtomcrypt/src/misc/crypt/crypt_fsa.c new file mode 100644 index 00000000000..ff77889ce6e --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/crypt/crypt_fsa.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" +#include + +/** + @file crypt_fsa.c + LibTomCrypt FULL SPEED AHEAD!, Tom St Denis +*/ + +/* format is ltc_mp, cipher_desc, [cipher_desc], NULL, hash_desc, [hash_desc], NULL, prng_desc, [prng_desc], NULL */ +int crypt_fsa(void *mp, ...) +{ + int err; + va_list args; + void *p; + + va_start(args, mp); + if (mp != NULL) { + XMEMCPY(<c_mp, mp, sizeof(ltc_mp)); + } + + while ((p = va_arg(args, void*)) != NULL) { + if ((err = register_cipher(p)) != CRYPT_OK) { + va_end(args); + return err; + } + } + + while ((p = va_arg(args, void*)) != NULL) { + if ((err = register_hash(p)) != CRYPT_OK) { + va_end(args); + return err; + } + } + + while ((p = va_arg(args, void*)) != NULL) { + if ((err = register_prng(p)) != CRYPT_OK) { + va_end(args); + return err; + } + } + + va_end(args); + return CRYPT_OK; +} + + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_fsa.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c b/core/lib/libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c new file mode 100644 index 00000000000..9aef6a50533 --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file crypt_hash_descriptor.c + Stores the hash descriptor table, Tom St Denis +*/ + +struct ltc_hash_descriptor hash_descriptor[TAB_SIZE] = { +{ NULL, 0, 0, 0, { 0 }, 0, NULL, NULL, NULL, NULL, NULL } +}; + +LTC_MUTEX_GLOBAL(ltc_hash_mutex) + + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c,v $ */ +/* $Revision: 1.10 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c b/core/lib/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c new file mode 100644 index 00000000000..8370bf03698 --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file crypt_hash_is_valid.c + Determine if hash is valid, Tom St Denis +*/ + +/* + Test if a hash index is valid + @param idx The index of the hash to search for + @return CRYPT_OK if valid +*/ +int hash_is_valid(int idx) +{ + LTC_MUTEX_LOCK(<c_hash_mutex); + if (idx < 0 || idx >= TAB_SIZE || hash_descriptor[idx].name == NULL) { + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return CRYPT_INVALID_HASH; + } + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return CRYPT_OK; +} + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c b/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c new file mode 100644 index 00000000000..5c9de43934c --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file crypt_prng_descriptor.c + Stores the PRNG descriptors, Tom St Denis +*/ +struct ltc_prng_descriptor prng_descriptor[TAB_SIZE] = { +{ NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } +}; + +LTC_MUTEX_GLOBAL(ltc_prng_mutex) + + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c b/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c new file mode 100644 index 00000000000..42e4d88c456 --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file crypt_prng_is_valid.c + Determine if PRNG is valid, Tom St Denis +*/ + +/* + Test if a PRNG index is valid + @param idx The index of the PRNG to search for + @return CRYPT_OK if valid +*/ +int prng_is_valid(int idx) +{ + LTC_MUTEX_LOCK(<c_prng_mutex); + if (idx < 0 || idx >= TAB_SIZE || prng_descriptor[idx].name == NULL) { + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return CRYPT_INVALID_PRNG; + } + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return CRYPT_OK; +} + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt_register_cipher.c b/core/lib/libtomcrypt/src/misc/crypt/crypt_register_cipher.c new file mode 100644 index 00000000000..232b159b06c --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/crypt/crypt_register_cipher.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file crypt_register_cipher.c + Register a cipher, Tom St Denis +*/ + +/** + Register a cipher with the descriptor table + @param cipher The cipher you wish to register + @return value >= 0 if successfully added (or already present), -1 if unsuccessful +*/ +int register_cipher(const struct ltc_cipher_descriptor *cipher) +{ + int x; + + LTC_ARGCHK(cipher != NULL); + + /* is it already registered? */ + LTC_MUTEX_LOCK(<c_cipher_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (cipher_descriptor[x].name != NULL && cipher_descriptor[x].ID == cipher->ID) { + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return x; + } + } + + /* find a blank spot */ + for (x = 0; x < TAB_SIZE; x++) { + if (cipher_descriptor[x].name == NULL) { + XMEMCPY(&cipher_descriptor[x], cipher, sizeof(struct ltc_cipher_descriptor)); + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return x; + } + } + + /* no spot */ + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return -1; +} + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_register_cipher.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt_register_hash.c b/core/lib/libtomcrypt/src/misc/crypt/crypt_register_hash.c new file mode 100644 index 00000000000..fe7fdd9a9ed --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/crypt/crypt_register_hash.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file crypt_register_hash.c + Register a HASH, Tom St Denis +*/ + +/** + Register a hash with the descriptor table + @param hash The hash you wish to register + @return value >= 0 if successfully added (or already present), -1 if unsuccessful +*/ +int register_hash(const struct ltc_hash_descriptor *hash) +{ + int x; + + LTC_ARGCHK(hash != NULL); + + /* is it already registered? */ + LTC_MUTEX_LOCK(<c_hash_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (XMEMCMP(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)) == 0) { + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return x; + } + } + + /* find a blank spot */ + for (x = 0; x < TAB_SIZE; x++) { + if (hash_descriptor[x].name == NULL) { + XMEMCPY(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)); + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return x; + } + } + + /* no spot */ + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return -1; +} + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_register_hash.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt_register_prng.c b/core/lib/libtomcrypt/src/misc/crypt/crypt_register_prng.c new file mode 100644 index 00000000000..60f347b1f25 --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/crypt/crypt_register_prng.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file crypt_register_prng.c + Register a PRNG, Tom St Denis +*/ + +/** + Register a PRNG with the descriptor table + @param prng The PRNG you wish to register + @return value >= 0 if successfully added (or already present), -1 if unsuccessful +*/ +int register_prng(const struct ltc_prng_descriptor *prng) +{ + int x; + + LTC_ARGCHK(prng != NULL); + + /* is it already registered? */ + LTC_MUTEX_LOCK(<c_prng_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (XMEMCMP(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)) == 0) { + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return x; + } + } + + /* find a blank spot */ + for (x = 0; x < TAB_SIZE; x++) { + if (prng_descriptor[x].name == NULL) { + XMEMCPY(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)); + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return x; + } + } + + /* no spot */ + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return -1; +} + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_register_prng.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_cipher.c b/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_cipher.c new file mode 100644 index 00000000000..55f480677a5 --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_cipher.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file crypt_unregister_cipher.c + Unregister a cipher, Tom St Denis +*/ + +/** + Unregister a cipher from the descriptor table + @param cipher The cipher descriptor to remove + @return CRYPT_OK on success +*/ +int unregister_cipher(const struct ltc_cipher_descriptor *cipher) +{ + int x; + + LTC_ARGCHK(cipher != NULL); + + /* is it already registered? */ + LTC_MUTEX_LOCK(<c_cipher_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (XMEMCMP(&cipher_descriptor[x], cipher, sizeof(struct ltc_cipher_descriptor)) == 0) { + cipher_descriptor[x].name = NULL; + cipher_descriptor[x].ID = 255; + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return CRYPT_OK; + } + } + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return CRYPT_ERROR; +} + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_unregister_cipher.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_hash.c b/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_hash.c new file mode 100644 index 00000000000..4bc27064944 --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_hash.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file crypt_unregister_hash.c + Unregister a hash, Tom St Denis +*/ + +/** + Unregister a hash from the descriptor table + @param hash The hash descriptor to remove + @return CRYPT_OK on success +*/ +int unregister_hash(const struct ltc_hash_descriptor *hash) +{ + int x; + + LTC_ARGCHK(hash != NULL); + + /* is it already registered? */ + LTC_MUTEX_LOCK(<c_hash_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (XMEMCMP(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)) == 0) { + hash_descriptor[x].name = NULL; + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return CRYPT_OK; + } + } + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return CRYPT_ERROR; +} + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_unregister_hash.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_prng.c b/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_prng.c new file mode 100644 index 00000000000..1a8872e9d68 --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_prng.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file crypt_unregister_prng.c + Unregister a PRNG, Tom St Denis +*/ + +/** + Unregister a PRNG from the descriptor table + @param prng The PRNG descriptor to remove + @return CRYPT_OK on success +*/ +int unregister_prng(const struct ltc_prng_descriptor *prng) +{ + int x; + + LTC_ARGCHK(prng != NULL); + + /* is it already registered? */ + LTC_MUTEX_LOCK(<c_prng_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (XMEMCMP(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)) != 0) { + prng_descriptor[x].name = NULL; + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return CRYPT_OK; + } + } + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return CRYPT_ERROR; +} + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_unregister_prng.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/misc/crypt/sub.mk b/core/lib/libtomcrypt/src/misc/crypt/sub.mk new file mode 100644 index 00000000000..9880a9be98c --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/crypt/sub.mk @@ -0,0 +1,22 @@ +srcs-y += crypt.c +srcs-y += crypt_cipher_descriptor.c +srcs-y += crypt_cipher_is_valid.c +srcs-y += crypt_find_cipher_any.c +srcs-y += crypt_find_cipher.c +srcs-y += crypt_find_cipher_id.c +srcs-y += crypt_find_hash_any.c +srcs-y += crypt_find_hash.c +srcs-y += crypt_find_hash_id.c +srcs-y += crypt_find_hash_oid.c +srcs-y += crypt_find_prng.c +srcs-y += crypt_fsa.c +srcs-y += crypt_hash_descriptor.c +srcs-y += crypt_hash_is_valid.c +srcs-y += crypt_prng_descriptor.c +srcs-y += crypt_prng_is_valid.c +srcs-y += crypt_register_cipher.c +srcs-y += crypt_register_hash.c +srcs-y += crypt_register_prng.c +srcs-y += crypt_unregister_cipher.c +srcs-y += crypt_unregister_hash.c +srcs-y += crypt_unregister_prng.c diff --git a/core/lib/libtomcrypt/src/misc/error_to_string.c b/core/lib/libtomcrypt/src/misc/error_to_string.c new file mode 100644 index 00000000000..fc110e51a87 --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/error_to_string.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +#include "tomcrypt.h" + +/** + @file error_to_string.c + Convert error codes to ASCII strings, Tom St Denis +*/ + +static const char *err_2_str[] = +{ + "CRYPT_OK", + "CRYPT_ERROR", + "Non-fatal 'no-operation' requested.", + + "Invalid keysize for block cipher.", + "Invalid number of rounds for block cipher.", + "Algorithm failed test vectors.", + + "Buffer overflow.", + "Invalid input packet.", + + "Invalid number of bits for a PRNG.", + "Error reading the PRNG.", + + "Invalid cipher specified.", + "Invalid hash specified.", + "Invalid PRNG specified.", + + "Out of memory.", + + "Invalid PK key or key type specified for function.", + "A private PK key is required.", + + "Invalid argument provided.", + "File Not Found", + + "Invalid PK type.", + "Invalid PK system.", + "Duplicate PK key found on keyring.", + "Key not found in keyring.", + "Invalid sized parameter.", + + "Invalid size for prime.", + +}; + +/** + Convert an LTC error code to ASCII + @param err The error code + @return A pointer to the ASCII NUL terminated string for the error or "Invalid error code." if the err code was not valid. +*/ +const char *error_to_string(int err) +{ + if (err < 0 || err >= (int)(sizeof(err_2_str)/sizeof(err_2_str[0]))) { + return "Invalid error code."; + } else { + return err_2_str[err]; + } +} + + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/error_to_string.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_1.c b/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_1.c new file mode 100644 index 00000000000..19d07efd0e3 --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_1.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include + +/** + @file pkcs_5_1.c + LTC_PKCS #5, Algorithm #1, Tom St Denis +*/ +#ifdef LTC_PKCS_5 +/** + Execute LTC_PKCS #5 v1 + @param password The password (or key) + @param password_len The length of the password (octet) + @param salt The salt (or nonce) which is 8 octets long + @param iteration_count The LTC_PKCS #5 v1 iteration count + @param hash_idx The index of the hash desired + @param out [out] The destination for this algorithm + @param outlen [in/out] The max size and resulting size of the algorithm output + @return CRYPT_OK if successful +*/ +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 err; + unsigned long x; + hash_state *md; + unsigned char *buf; + + LTC_ARGCHK(password != NULL); + LTC_ARGCHK(salt != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* test hash IDX */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + + /* allocate memory */ + md = XMALLOC(sizeof(hash_state)); + buf = XMALLOC(MAXBLOCKSIZE); + if (md == NULL || buf == NULL) { + if (md != NULL) { + XFREE(md); + } + if (buf != NULL) { + XFREE(buf); + } + return CRYPT_MEM; + } + + /* hash initial password + salt */ + if ((err = hash_descriptor[hash_idx].init(md)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash_idx].process(md, password, password_len)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash_idx].process(md, salt, 8)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash_idx].done(md, buf)) != CRYPT_OK) { + goto LBL_ERR; + } + + while (--iteration_count) { + /* code goes here. */ + x = MAXBLOCKSIZE; + if ((err = hash_memory(hash_idx, buf, hash_descriptor[hash_idx].hashsize, buf, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + } + + /* copy upto outlen bytes */ + for (x = 0; x < hash_descriptor[hash_idx].hashsize && x < *outlen; x++) { + out[x] = buf[x]; + } + *outlen = x; + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(buf, MAXBLOCKSIZE); + zeromem(md, sizeof(hash_state)); +#endif + + XFREE(buf); + XFREE(md); + + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/pkcs5/pkcs_5_1.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_2.c b/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_2.c new file mode 100644 index 00000000000..b9697986778 --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_2.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include + +/** + @file pkcs_5_2.c + LTC_PKCS #5, Algorithm #2, Tom St Denis +*/ +#ifdef LTC_PKCS_5 + +/** + Execute LTC_PKCS #5 v2 + @param password The input password (or key) + @param password_len The length of the password (octets) + @param salt The salt (or nonce) + @param salt_len The length of the salt (octets) + @param iteration_count # of iterations desired for LTC_PKCS #5 v2 [read specs for more] + @param hash_idx The index of the hash desired + @param out [out] The destination for this algorithm + @param outlen [in/out] The max size and resulting size of the algorithm output + @return CRYPT_OK if successful +*/ +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 err, itts; + ulong32 blkno; + unsigned long stored, left, x, y; + unsigned char *buf[2]; + hmac_state *hmac; + + LTC_ARGCHK(password != NULL); + LTC_ARGCHK(salt != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* test hash IDX */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + + buf[0] = XMALLOC(MAXBLOCKSIZE * 2); + hmac = XMALLOC(sizeof(hmac_state)); + if (hmac == NULL || buf[0] == NULL) { + if (hmac != NULL) { + XFREE(hmac); + } + if (buf[0] != NULL) { + XFREE(buf[0]); + } + return CRYPT_MEM; + } + /* buf[1] points to the second block of MAXBLOCKSIZE bytes */ + buf[1] = buf[0] + MAXBLOCKSIZE; + + left = *outlen; + blkno = 1; + stored = 0; + while (left != 0) { + /* process block number blkno */ + zeromem(buf[0], MAXBLOCKSIZE*2); + + /* store current block number and increment for next pass */ + STORE32H(blkno, buf[1]); + ++blkno; + + /* get PRF(P, S||int(blkno)) */ + if ((err = hmac_init(hmac, hash_idx, password, password_len)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hmac_process(hmac, salt, salt_len)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hmac_process(hmac, buf[1], 4)) != CRYPT_OK) { + goto LBL_ERR; + } + x = MAXBLOCKSIZE; + if ((err = hmac_done(hmac, buf[0], &x)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* now compute repeated and XOR it in buf[1] */ + XMEMCPY(buf[1], buf[0], x); + for (itts = 1; itts < iteration_count; ++itts) { + if ((err = hmac_memory(hash_idx, password, password_len, buf[0], x, buf[0], &x)) != CRYPT_OK) { + goto LBL_ERR; + } + for (y = 0; y < x; y++) { + buf[1][y] ^= buf[0][y]; + } + } + + /* now emit upto x bytes of buf[1] to output */ + for (y = 0; y < x && left != 0; ++y) { + out[stored++] = buf[1][y]; + --left; + } + } + *outlen = stored; + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(buf[0], MAXBLOCKSIZE*2); + zeromem(hmac, sizeof(hmac_state)); +#endif + + XFREE(hmac); + XFREE(buf[0]); + + return err; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/pkcs5/pkcs_5_2.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/misc/pkcs5/sub.mk b/core/lib/libtomcrypt/src/misc/pkcs5/sub.mk new file mode 100644 index 00000000000..7f8ccfe714f --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/pkcs5/sub.mk @@ -0,0 +1,2 @@ +srcs-y += pkcs_5_1.c +srcs-y += pkcs_5_2.c diff --git a/core/lib/libtomcrypt/src/misc/sub.mk b/core/lib/libtomcrypt/src/misc/sub.mk new file mode 100644 index 00000000000..6b6021372c3 --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/sub.mk @@ -0,0 +1,6 @@ +srcs-y += burn_stack.c +srcs-y += error_to_string.c +srcs-y += zeromem.c +subdirs-y += base64 +subdirs-y += crypt +subdirs-y += pkcs5 diff --git a/core/lib/libtomcrypt/src/misc/zeromem.c b/core/lib/libtomcrypt/src/misc/zeromem.c new file mode 100644 index 00000000000..ece037b91d7 --- /dev/null +++ b/core/lib/libtomcrypt/src/misc/zeromem.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file zeromem.c + Zero a block of memory, Tom St Denis +*/ + +/** + Zero a block of memory + @param out The destination of the area to zero + @param outlen The length of the area to zero (octets) +*/ +void zeromem(void *out, size_t outlen) +{ + unsigned char *mem = out; + LTC_ARGCHKVD(out != NULL); + while (outlen-- > 0) { + *mem++ = 0; + } +} + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/zeromem.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/cbc/cbc_decrypt.c b/core/lib/libtomcrypt/src/modes/cbc/cbc_decrypt.c new file mode 100644 index 00000000000..cee920ccddc --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/cbc/cbc_decrypt.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file cbc_decrypt.c + CBC implementation, encrypt block, Tom St Denis +*/ + + +#ifdef LTC_CBC_MODE + +/** + CBC decrypt + @param ct Ciphertext + @param pt [out] Plaintext + @param len The number of bytes to process (must be multiple of block length) + @param cbc CBC state + @return CRYPT_OK if successful +*/ +int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc) +{ + int x, err; + unsigned char tmp[16]; +#ifdef LTC_FAST + LTC_FAST_TYPE tmpy; +#else + unsigned char tmpy; +#endif + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(cbc != NULL); + + if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) { + return err; + } + + /* is blocklen valid? */ + if (cbc->blocklen < 1 || cbc->blocklen > (int)sizeof(cbc->IV)) { + return CRYPT_INVALID_ARG; + } + + if (len % cbc->blocklen) { + return CRYPT_INVALID_ARG; + } +#ifdef LTC_FAST + if (cbc->blocklen % sizeof(LTC_FAST_TYPE)) { + return CRYPT_INVALID_ARG; + } +#endif + + if (cipher_descriptor[cbc->cipher].accel_cbc_decrypt != NULL) { + return cipher_descriptor[cbc->cipher].accel_cbc_decrypt(ct, pt, len / cbc->blocklen, cbc->IV, &cbc->key); + } else { + while (len) { + /* decrypt */ + if ((err = cipher_descriptor[cbc->cipher].ecb_decrypt(ct, tmp, &cbc->key)) != CRYPT_OK) { + return err; + } + + /* xor IV against plaintext */ + #if defined(LTC_FAST) + for (x = 0; x < cbc->blocklen; x += sizeof(LTC_FAST_TYPE)) { + tmpy = *((LTC_FAST_TYPE*)((unsigned char *)cbc->IV + x)) ^ *((LTC_FAST_TYPE*)((unsigned char *)tmp + x)); + *((LTC_FAST_TYPE*)((unsigned char *)cbc->IV + x)) = *((LTC_FAST_TYPE*)((unsigned char *)ct + x)); + *((LTC_FAST_TYPE*)((unsigned char *)pt + x)) = tmpy; + } + #else + for (x = 0; x < cbc->blocklen; x++) { + tmpy = tmp[x] ^ cbc->IV[x]; + cbc->IV[x] = ct[x]; + pt[x] = tmpy; + } + #endif + + ct += cbc->blocklen; + pt += cbc->blocklen; + len -= cbc->blocklen; + } + } + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/cbc/cbc_decrypt.c,v $ */ +/* $Revision: 1.16 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/cbc/cbc_done.c b/core/lib/libtomcrypt/src/modes/cbc/cbc_done.c new file mode 100644 index 00000000000..4577d3e509e --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/cbc/cbc_done.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file cbc_done.c + CBC implementation, finish chain, Tom St Denis +*/ + +#ifdef LTC_CBC_MODE + +/** Terminate the chain + @param cbc The CBC chain to terminate + @return CRYPT_OK on success +*/ +int cbc_done(symmetric_CBC *cbc) +{ + int err; + LTC_ARGCHK(cbc != NULL); + + if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) { + return err; + } + cipher_descriptor[cbc->cipher].done(&cbc->key); + return CRYPT_OK; +} + + + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/cbc/cbc_done.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/cbc/cbc_encrypt.c b/core/lib/libtomcrypt/src/modes/cbc/cbc_encrypt.c new file mode 100644 index 00000000000..35fda53e2f5 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/cbc/cbc_encrypt.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file cbc_encrypt.c + CBC implementation, encrypt block, Tom St Denis +*/ + + +#ifdef LTC_CBC_MODE + +/** + CBC encrypt + @param pt Plaintext + @param ct [out] Ciphertext + @param len The number of bytes to process (must be multiple of block length) + @param cbc CBC state + @return CRYPT_OK if successful +*/ +int cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CBC *cbc) +{ + int x, err; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(cbc != NULL); + + if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) { + return err; + } + + /* is blocklen valid? */ + if (cbc->blocklen < 1 || cbc->blocklen > (int)sizeof(cbc->IV)) { + return CRYPT_INVALID_ARG; + } + + if (len % cbc->blocklen) { + return CRYPT_INVALID_ARG; + } +#ifdef LTC_FAST + if (cbc->blocklen % sizeof(LTC_FAST_TYPE)) { + return CRYPT_INVALID_ARG; + } +#endif + + if (cipher_descriptor[cbc->cipher].accel_cbc_encrypt != NULL) { + return cipher_descriptor[cbc->cipher].accel_cbc_encrypt(pt, ct, len / cbc->blocklen, cbc->IV, &cbc->key); + } else { + while (len) { + /* xor IV against plaintext */ + #if defined(LTC_FAST) + for (x = 0; x < cbc->blocklen; x += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE*)((unsigned char *)cbc->IV + x)) ^= *((LTC_FAST_TYPE*)((unsigned char *)pt + x)); + } + #else + for (x = 0; x < cbc->blocklen; x++) { + cbc->IV[x] ^= pt[x]; + } + #endif + + /* encrypt */ + if ((err = cipher_descriptor[cbc->cipher].ecb_encrypt(cbc->IV, ct, &cbc->key)) != CRYPT_OK) { + return err; + } + + /* store IV [ciphertext] for a future block */ + #if defined(LTC_FAST) + for (x = 0; x < cbc->blocklen; x += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE*)((unsigned char *)cbc->IV + x)) = *((LTC_FAST_TYPE*)((unsigned char *)ct + x)); + } + #else + for (x = 0; x < cbc->blocklen; x++) { + cbc->IV[x] = ct[x]; + } + #endif + + ct += cbc->blocklen; + pt += cbc->blocklen; + len -= cbc->blocklen; + } + } + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/cbc/cbc_encrypt.c,v $ */ +/* $Revision: 1.14 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/cbc/cbc_getiv.c b/core/lib/libtomcrypt/src/modes/cbc/cbc_getiv.c new file mode 100644 index 00000000000..799ac962bf9 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/cbc/cbc_getiv.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file cbc_getiv.c + CBC implementation, get IV, Tom St Denis +*/ + +#ifdef LTC_CBC_MODE + +/** + Get the current initial vector + @param IV [out] The destination of the initial vector + @param len [in/out] The max size and resulting size of the initial vector + @param cbc The CBC state + @return CRYPT_OK if successful +*/ +int cbc_getiv(unsigned char *IV, unsigned long *len, symmetric_CBC *cbc) +{ + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(len != NULL); + LTC_ARGCHK(cbc != NULL); + if ((unsigned long)cbc->blocklen > *len) { + *len = cbc->blocklen; + return CRYPT_BUFFER_OVERFLOW; + } + XMEMCPY(IV, cbc->IV, cbc->blocklen); + *len = cbc->blocklen; + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/cbc/cbc_getiv.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/cbc/cbc_setiv.c b/core/lib/libtomcrypt/src/modes/cbc/cbc_setiv.c new file mode 100644 index 00000000000..05e3ee94998 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/cbc/cbc_setiv.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file cbc_setiv.c + CBC implementation, set IV, Tom St Denis +*/ + + +#ifdef LTC_CBC_MODE + +/** + Set an initial vector + @param IV The initial vector + @param len The length of the vector (in octets) + @param cbc The CBC state + @return CRYPT_OK if successful +*/ +int cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc) +{ + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(cbc != NULL); + if (len != (unsigned long)cbc->blocklen) { + return CRYPT_INVALID_ARG; + } + XMEMCPY(cbc->IV, IV, len); + return CRYPT_OK; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/cbc/cbc_setiv.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/cbc/cbc_start.c b/core/lib/libtomcrypt/src/modes/cbc/cbc_start.c new file mode 100644 index 00000000000..cdf269ebd65 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/cbc/cbc_start.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file cbc_start.c + CBC implementation, start chain, Tom St Denis +*/ + +#ifdef LTC_CBC_MODE + +/** + Initialize a CBC context + @param cipher The index of the cipher desired + @param IV The initial vector + @param key The secret key + @param keylen The length of the secret key (octets) + @param num_rounds Number of rounds in the cipher desired (0 for default) + @param cbc The CBC state to initialize + @return CRYPT_OK if successful +*/ +int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key, + int keylen, int num_rounds, symmetric_CBC *cbc) +{ + int x, err; + + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(cbc != NULL); + + /* bad param? */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + /* setup cipher */ + if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &cbc->key)) != CRYPT_OK) { + return err; + } + + /* copy IV */ + cbc->blocklen = cipher_descriptor[cipher].block_length; + cbc->cipher = cipher; + for (x = 0; x < cbc->blocklen; x++) { + cbc->IV[x] = IV[x]; + } + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/cbc/cbc_start.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/cbc/sub.mk b/core/lib/libtomcrypt/src/modes/cbc/sub.mk new file mode 100644 index 00000000000..1ce3e771b30 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/cbc/sub.mk @@ -0,0 +1,6 @@ +srcs-y += cbc_decrypt.c +srcs-y += cbc_done.c +srcs-y += cbc_encrypt.c +srcs-y += cbc_getiv.c +srcs-y += cbc_setiv.c +srcs-y += cbc_start.c diff --git a/core/lib/libtomcrypt/src/modes/cfb/cfb_decrypt.c b/core/lib/libtomcrypt/src/modes/cfb/cfb_decrypt.c new file mode 100644 index 00000000000..7ca938f1045 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/cfb/cfb_decrypt.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file cfb_decrypt.c + CFB implementation, decrypt data, Tom St Denis +*/ + +#ifdef LTC_CFB_MODE + +/** + CFB decrypt + @param ct Ciphertext + @param pt [out] Plaintext + @param len Length of ciphertext (octets) + @param cfb CFB state + @return CRYPT_OK if successful +*/ +int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb) +{ + int err; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(cfb != NULL); + + if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) { + return err; + } + + /* is blocklen/padlen valid? */ + if (cfb->blocklen < 0 || cfb->blocklen > (int)sizeof(cfb->IV) || + cfb->padlen < 0 || cfb->padlen > (int)sizeof(cfb->pad)) { + return CRYPT_INVALID_ARG; + } + + while (len-- > 0) { + if (cfb->padlen == cfb->blocklen) { + if ((err = cipher_descriptor[cfb->cipher].ecb_encrypt(cfb->pad, cfb->IV, &cfb->key)) != CRYPT_OK) { + return err; + } + cfb->padlen = 0; + } + cfb->pad[cfb->padlen] = *ct; + *pt = *ct ^ cfb->IV[cfb->padlen]; + ++pt; + ++ct; + ++(cfb->padlen); + } + return CRYPT_OK; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/cfb/cfb_decrypt.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/cfb/cfb_done.c b/core/lib/libtomcrypt/src/modes/cfb/cfb_done.c new file mode 100644 index 00000000000..9f84727ba5e --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/cfb/cfb_done.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file cfb_done.c + CFB implementation, finish chain, Tom St Denis +*/ + +#ifdef LTC_CFB_MODE + +/** Terminate the chain + @param cfb The CFB chain to terminate + @return CRYPT_OK on success +*/ +int cfb_done(symmetric_CFB *cfb) +{ + int err; + LTC_ARGCHK(cfb != NULL); + + if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) { + return err; + } + cipher_descriptor[cfb->cipher].done(&cfb->key); + return CRYPT_OK; +} + + + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/cfb/cfb_done.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/cfb/cfb_encrypt.c b/core/lib/libtomcrypt/src/modes/cfb/cfb_encrypt.c new file mode 100644 index 00000000000..4acb8f14eb2 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/cfb/cfb_encrypt.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file cfb_encrypt.c + CFB implementation, encrypt data, Tom St Denis +*/ + +#ifdef LTC_CFB_MODE + +/** + CFB encrypt + @param pt Plaintext + @param ct [out] Ciphertext + @param len Length of plaintext (octets) + @param cfb CFB state + @return CRYPT_OK if successful +*/ +int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb) +{ + int err; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(cfb != NULL); + + if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) { + return err; + } + + /* is blocklen/padlen valid? */ + if (cfb->blocklen < 0 || cfb->blocklen > (int)sizeof(cfb->IV) || + cfb->padlen < 0 || cfb->padlen > (int)sizeof(cfb->pad)) { + return CRYPT_INVALID_ARG; + } + + while (len-- > 0) { + if (cfb->padlen == cfb->blocklen) { + if ((err = cipher_descriptor[cfb->cipher].ecb_encrypt(cfb->pad, cfb->IV, &cfb->key)) != CRYPT_OK) { + return err; + } + cfb->padlen = 0; + } + cfb->pad[cfb->padlen] = (*ct = *pt ^ cfb->IV[cfb->padlen]); + ++pt; + ++ct; + ++(cfb->padlen); + } + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/cfb/cfb_encrypt.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/cfb/cfb_getiv.c b/core/lib/libtomcrypt/src/modes/cfb/cfb_getiv.c new file mode 100644 index 00000000000..0adb1f63500 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/cfb/cfb_getiv.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file cfb_getiv.c + CFB implementation, get IV, Tom St Denis +*/ + +#ifdef LTC_CFB_MODE + +/** + Get the current initial vector + @param IV [out] The destination of the initial vector + @param len [in/out] The max size and resulting size of the initial vector + @param cfb The CFB state + @return CRYPT_OK if successful +*/ +int cfb_getiv(unsigned char *IV, unsigned long *len, symmetric_CFB *cfb) +{ + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(len != NULL); + LTC_ARGCHK(cfb != NULL); + if ((unsigned long)cfb->blocklen > *len) { + *len = cfb->blocklen; + return CRYPT_BUFFER_OVERFLOW; + } + XMEMCPY(IV, cfb->IV, cfb->blocklen); + *len = cfb->blocklen; + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/cfb/cfb_getiv.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/cfb/cfb_setiv.c b/core/lib/libtomcrypt/src/modes/cfb/cfb_setiv.c new file mode 100644 index 00000000000..26cc81bf6c9 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/cfb/cfb_setiv.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file cfb_setiv.c + CFB implementation, set IV, Tom St Denis +*/ + +#ifdef LTC_CFB_MODE + +/** + Set an initial vector + @param IV The initial vector + @param len The length of the vector (in octets) + @param cfb The CFB state + @return CRYPT_OK if successful +*/ +int cfb_setiv(const unsigned char *IV, unsigned long len, symmetric_CFB *cfb) +{ + int err; + + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(cfb != NULL); + + if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) { + return err; + } + + if (len != (unsigned long)cfb->blocklen) { + return CRYPT_INVALID_ARG; + } + + /* force next block */ + cfb->padlen = 0; + return cipher_descriptor[cfb->cipher].ecb_encrypt(IV, cfb->IV, &cfb->key); +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/cfb/cfb_setiv.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/cfb/cfb_start.c b/core/lib/libtomcrypt/src/modes/cfb/cfb_start.c new file mode 100644 index 00000000000..3a691ec1dbd --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/cfb/cfb_start.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file cfb_start.c + CFB implementation, start chain, Tom St Denis +*/ + + +#ifdef LTC_CFB_MODE + +/** + Initialize a CFB context + @param cipher The index of the cipher desired + @param IV The initial vector + @param key The secret key + @param keylen The length of the secret key (octets) + @param num_rounds Number of rounds in the cipher desired (0 for default) + @param cfb The CFB state to initialize + @return CRYPT_OK if successful +*/ +int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key, + int keylen, int num_rounds, symmetric_CFB *cfb) +{ + int x, err; + + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(cfb != NULL); + + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + + /* copy data */ + cfb->cipher = cipher; + cfb->blocklen = cipher_descriptor[cipher].block_length; + for (x = 0; x < cfb->blocklen; x++) + cfb->IV[x] = IV[x]; + + /* init the cipher */ + if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &cfb->key)) != CRYPT_OK) { + return err; + } + + /* encrypt the IV */ + cfb->padlen = 0; + return cipher_descriptor[cfb->cipher].ecb_encrypt(cfb->IV, cfb->IV, &cfb->key); +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/cfb/cfb_start.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/cfb/sub.mk b/core/lib/libtomcrypt/src/modes/cfb/sub.mk new file mode 100644 index 00000000000..7a92b019559 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/cfb/sub.mk @@ -0,0 +1,6 @@ +srcs-y += cfb_decrypt.c +srcs-y += cfb_done.c +srcs-y += cfb_encrypt.c +srcs-y += cfb_getiv.c +srcs-y += cfb_setiv.c +srcs-y += cfb_start.c diff --git a/core/lib/libtomcrypt/src/modes/ctr/ctr_decrypt.c b/core/lib/libtomcrypt/src/modes/ctr/ctr_decrypt.c new file mode 100644 index 00000000000..834df8a83f1 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/ctr/ctr_decrypt.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file ctr_decrypt.c + CTR implementation, decrypt data, Tom St Denis +*/ + +#ifdef LTC_CTR_MODE + +/** + CTR decrypt + @param ct Ciphertext + @param pt [out] Plaintext + @param len Length of ciphertext (octets) + @param ctr CTR state + @return CRYPT_OK if successful +*/ +int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr) +{ + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(ctr != NULL); + + return ctr_encrypt(ct, pt, len, ctr); +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/ctr/ctr_decrypt.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/ctr/ctr_done.c b/core/lib/libtomcrypt/src/modes/ctr/ctr_done.c new file mode 100644 index 00000000000..581fd1b4880 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/ctr/ctr_done.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file ctr_done.c + CTR implementation, finish chain, Tom St Denis +*/ + +#ifdef LTC_CTR_MODE + +/** Terminate the chain + @param ctr The CTR chain to terminate + @return CRYPT_OK on success +*/ +int ctr_done(symmetric_CTR *ctr) +{ + int err; + LTC_ARGCHK(ctr != NULL); + + if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) { + return err; + } + cipher_descriptor[ctr->cipher].done(&ctr->key); + return CRYPT_OK; +} + + + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/ctr/ctr_done.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/ctr/ctr_encrypt.c b/core/lib/libtomcrypt/src/modes/ctr/ctr_encrypt.c new file mode 100644 index 00000000000..b5136da71d5 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/ctr/ctr_encrypt.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file ctr_encrypt.c + CTR implementation, encrypt data, Tom St Denis +*/ + + +#ifdef LTC_CTR_MODE + +/** + CTR encrypt + @param pt Plaintext + @param ct [out] Ciphertext + @param len Length of plaintext (octets) + @param ctr CTR state + @return CRYPT_OK if successful +*/ +int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr) +{ + int x, err; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(ctr != NULL); + + if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) { + return err; + } + + /* is blocklen/padlen valid? */ + if (ctr->blocklen < 1 || ctr->blocklen > (int)sizeof(ctr->ctr) || + ctr->padlen < 0 || ctr->padlen > (int)sizeof(ctr->pad)) { + return CRYPT_INVALID_ARG; + } + +#ifdef LTC_FAST + if (ctr->blocklen % sizeof(LTC_FAST_TYPE)) { + return CRYPT_INVALID_ARG; + } +#endif + + /* handle acceleration only if pad is empty, accelerator is present and length is >= a block size */ + if ((ctr->padlen == ctr->blocklen) && cipher_descriptor[ctr->cipher].accel_ctr_encrypt != NULL && (len >= (unsigned long)ctr->blocklen)) { + if ((err = cipher_descriptor[ctr->cipher].accel_ctr_encrypt(pt, ct, len/ctr->blocklen, ctr->ctr, ctr->mode, &ctr->key)) != CRYPT_OK) { + return err; + } + len %= ctr->blocklen; + } + + while (len) { + /* is the pad empty? */ + if (ctr->padlen == ctr->blocklen) { + /* increment counter */ + if (ctr->mode == CTR_COUNTER_LITTLE_ENDIAN) { + /* little-endian */ + for (x = 0; x < ctr->ctrlen; x++) { + ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255; + if (ctr->ctr[x] != (unsigned char)0) { + break; + } + } + } else { + /* big-endian */ + for (x = ctr->blocklen-1; x >= ctr->ctrlen; x--) { + ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255; + if (ctr->ctr[x] != (unsigned char)0) { + break; + } + } + } + + /* encrypt it */ + if ((err = cipher_descriptor[ctr->cipher].ecb_encrypt(ctr->ctr, ctr->pad, &ctr->key)) != CRYPT_OK) { + return err; + } + ctr->padlen = 0; + } +#ifdef LTC_FAST + if (ctr->padlen == 0 && len >= (unsigned long)ctr->blocklen) { + for (x = 0; x < ctr->blocklen; x += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE*)((unsigned char *)ct + x)) = *((LTC_FAST_TYPE*)((unsigned char *)pt + x)) ^ + *((LTC_FAST_TYPE*)((unsigned char *)ctr->pad + x)); + } + pt += ctr->blocklen; + ct += ctr->blocklen; + len -= ctr->blocklen; + ctr->padlen = ctr->blocklen; + continue; + } +#endif + *ct++ = *pt++ ^ ctr->pad[ctr->padlen++]; + --len; + } + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/ctr/ctr_encrypt.c,v $ */ +/* $Revision: 1.22 $ */ +/* $Date: 2007/02/22 20:26:05 $ */ diff --git a/core/lib/libtomcrypt/src/modes/ctr/ctr_getiv.c b/core/lib/libtomcrypt/src/modes/ctr/ctr_getiv.c new file mode 100644 index 00000000000..0ccb2fe1d1a --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/ctr/ctr_getiv.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file ctr_getiv.c + CTR implementation, get IV, Tom St Denis +*/ + +#ifdef LTC_CTR_MODE + +/** + Get the current initial vector + @param IV [out] The destination of the initial vector + @param len [in/out] The max size and resulting size of the initial vector + @param ctr The CTR state + @return CRYPT_OK if successful +*/ +int ctr_getiv(unsigned char *IV, unsigned long *len, symmetric_CTR *ctr) +{ + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(len != NULL); + LTC_ARGCHK(ctr != NULL); + if ((unsigned long)ctr->blocklen > *len) { + *len = ctr->blocklen; + return CRYPT_BUFFER_OVERFLOW; + } + XMEMCPY(IV, ctr->ctr, ctr->blocklen); + *len = ctr->blocklen; + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/ctr/ctr_getiv.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/ctr/ctr_setiv.c b/core/lib/libtomcrypt/src/modes/ctr/ctr_setiv.c new file mode 100644 index 00000000000..264674e80c0 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/ctr/ctr_setiv.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file ctr_setiv.c + CTR implementation, set IV, Tom St Denis +*/ + +#ifdef LTC_CTR_MODE + +/** + Set an initial vector + @param IV The initial vector + @param len The length of the vector (in octets) + @param ctr The CTR state + @return CRYPT_OK if successful +*/ +int ctr_setiv(const unsigned char *IV, unsigned long len, symmetric_CTR *ctr) +{ + int err; + + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(ctr != NULL); + + /* bad param? */ + if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) { + return err; + } + + if (len != (unsigned long)ctr->blocklen) { + return CRYPT_INVALID_ARG; + } + + /* set IV */ + XMEMCPY(ctr->ctr, IV, len); + + /* force next block */ + ctr->padlen = 0; + return cipher_descriptor[ctr->cipher].ecb_encrypt(IV, ctr->pad, &ctr->key); +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/ctr/ctr_setiv.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/ctr/ctr_start.c b/core/lib/libtomcrypt/src/modes/ctr/ctr_start.c new file mode 100644 index 00000000000..8ac0980afb3 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/ctr/ctr_start.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file ctr_start.c + CTR implementation, start chain, Tom St Denis +*/ + + +#ifdef LTC_CTR_MODE + +/** + Initialize a CTR context + @param cipher The index of the cipher desired + @param IV The initial vector + @param key The secret key + @param keylen The length of the secret key (octets) + @param num_rounds Number of rounds in the cipher desired (0 for default) + @param ctr_mode The counter mode (CTR_COUNTER_LITTLE_ENDIAN or CTR_COUNTER_BIG_ENDIAN) + @param ctr The CTR state to initialize + @return CRYPT_OK if successful +*/ +int ctr_start( int cipher, + const unsigned char *IV, + const unsigned char *key, int keylen, + int num_rounds, int ctr_mode, + symmetric_CTR *ctr) +{ + int x, err; + + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ctr != NULL); + + /* bad param? */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + /* ctrlen == counter width */ + ctr->ctrlen = (ctr_mode & 255) ? (ctr_mode & 255) : cipher_descriptor[cipher].block_length; + if (ctr->ctrlen > cipher_descriptor[cipher].block_length) { + return CRYPT_INVALID_ARG; + } + + if ((ctr_mode & 0x1000) == CTR_COUNTER_BIG_ENDIAN) { + ctr->ctrlen = cipher_descriptor[cipher].block_length - ctr->ctrlen; + } + + /* setup cipher */ + if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ctr->key)) != CRYPT_OK) { + return err; + } + + /* copy ctr */ + ctr->blocklen = cipher_descriptor[cipher].block_length; + ctr->cipher = cipher; + ctr->padlen = 0; + ctr->mode = ctr_mode & 0x1000; + for (x = 0; x < ctr->blocklen; x++) { + ctr->ctr[x] = IV[x]; + } + + if (ctr_mode & LTC_CTR_RFC3686) { + /* increment the IV as per RFC 3686 */ + if (ctr->mode == CTR_COUNTER_LITTLE_ENDIAN) { + /* little-endian */ + for (x = 0; x < ctr->ctrlen; x++) { + ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255; + if (ctr->ctr[x] != (unsigned char)0) { + break; + } + } + } else { + /* big-endian */ + for (x = ctr->blocklen-1; x >= ctr->ctrlen; x--) { + ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255; + if (ctr->ctr[x] != (unsigned char)0) { + break; + } + } + } + } + + return cipher_descriptor[ctr->cipher].ecb_encrypt(ctr->ctr, ctr->pad, &ctr->key); +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/ctr/ctr_start.c,v $ */ +/* $Revision: 1.15 $ */ +/* $Date: 2007/02/23 14:18:37 $ */ diff --git a/core/lib/libtomcrypt/src/modes/ctr/ctr_test.c b/core/lib/libtomcrypt/src/modes/ctr/ctr_test.c new file mode 100644 index 00000000000..ce9db100b34 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/ctr/ctr_test.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file ctr_test.c + CTR implementation, Tests again RFC 3686, Tom St Denis +*/ + +#ifdef LTC_CTR_MODE + +int ctr_test(void) +{ +#ifdef LTC_NO_TEST + return CRYPT_NOP; +#else + static const struct { + int keylen, msglen; + unsigned char key[32], IV[16], pt[64], ct[64]; + } tests[] = { +/* 128-bit key, 16-byte pt */ +{ + 16, 16, + {0xAE,0x68,0x52,0xF8,0x12,0x10,0x67,0xCC,0x4B,0xF7,0xA5,0x76,0x55,0x77,0xF3,0x9E }, + {0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + {0x53,0x69,0x6E,0x67,0x6C,0x65,0x20,0x62,0x6C,0x6F,0x63,0x6B,0x20,0x6D,0x73,0x67 }, + {0xE4,0x09,0x5D,0x4F,0xB7,0xA7,0xB3,0x79,0x2D,0x61,0x75,0xA3,0x26,0x13,0x11,0xB8 }, +}, + +/* 128-bit key, 36-byte pt */ +{ + 16, 36, + {0x76,0x91,0xBE,0x03,0x5E,0x50,0x20,0xA8,0xAC,0x6E,0x61,0x85,0x29,0xF9,0xA0,0xDC }, + {0x00,0xE0,0x01,0x7B,0x27,0x77,0x7F,0x3F,0x4A,0x17,0x86,0xF0,0x00,0x00,0x00,0x00 }, + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, + 0x20,0x21,0x22,0x23}, + {0xC1,0xCF,0x48,0xA8,0x9F,0x2F,0xFD,0xD9,0xCF,0x46,0x52,0xE9,0xEF,0xDB,0x72,0xD7, + 0x45,0x40,0xA4,0x2B,0xDE,0x6D,0x78,0x36,0xD5,0x9A,0x5C,0xEA,0xAE,0xF3,0x10,0x53, + 0x25,0xB2,0x07,0x2F }, +}, +}; + int idx, err, x; + unsigned char buf[64]; + symmetric_CTR ctr; + + /* AES can be under rijndael or aes... try to find it */ + if ((idx = find_cipher("aes")) == -1) { + if ((idx = find_cipher("rijndael")) == -1) { + return CRYPT_NOP; + } + } + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + if ((err = ctr_start(idx, tests[x].IV, tests[x].key, tests[x].keylen, 0, CTR_COUNTER_BIG_ENDIAN|LTC_CTR_RFC3686, &ctr)) != CRYPT_OK) { + return err; + } + if ((err = ctr_encrypt(tests[x].pt, buf, tests[x].msglen, &ctr)) != CRYPT_OK) { + return err; + } + ctr_done(&ctr); + if (XMEMCMP(buf, tests[x].ct, tests[x].msglen)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/ctr/ctr_test.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/ctr/sub.mk b/core/lib/libtomcrypt/src/modes/ctr/sub.mk new file mode 100644 index 00000000000..69a2160329d --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/ctr/sub.mk @@ -0,0 +1,7 @@ +srcs-y += ctr_decrypt.c +srcs-y += ctr_done.c +srcs-y += ctr_encrypt.c +srcs-y += ctr_getiv.c +srcs-y += ctr_setiv.c +srcs-y += ctr_start.c +srcs-y += ctr_test.c diff --git a/core/lib/libtomcrypt/src/modes/ecb/ecb_decrypt.c b/core/lib/libtomcrypt/src/modes/ecb/ecb_decrypt.c new file mode 100644 index 00000000000..459af28e0b7 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/ecb/ecb_decrypt.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file ecb_decrypt.c + ECB implementation, decrypt a block, Tom St Denis +*/ + +#ifdef LTC_ECB_MODE + +/** + ECB decrypt + @param ct Ciphertext + @param pt [out] Plaintext + @param len The number of octets to process (must be multiple of the cipher block size) + @param ecb ECB state + @return CRYPT_OK if successful +*/ +int ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_ECB *ecb) +{ + int err; + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(ecb != NULL); + if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) { + return err; + } + if (len % cipher_descriptor[ecb->cipher].block_length) { + return CRYPT_INVALID_ARG; + } + + /* check for accel */ + if (cipher_descriptor[ecb->cipher].accel_ecb_decrypt != NULL) { + return cipher_descriptor[ecb->cipher].accel_ecb_decrypt(ct, pt, len / cipher_descriptor[ecb->cipher].block_length, &ecb->key); + } else { + while (len) { + if ((err = cipher_descriptor[ecb->cipher].ecb_decrypt(ct, pt, &ecb->key)) != CRYPT_OK) { + return err; + } + pt += cipher_descriptor[ecb->cipher].block_length; + ct += cipher_descriptor[ecb->cipher].block_length; + len -= cipher_descriptor[ecb->cipher].block_length; + } + } + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/ecb/ecb_decrypt.c,v $ */ +/* $Revision: 1.10 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/ecb/ecb_done.c b/core/lib/libtomcrypt/src/modes/ecb/ecb_done.c new file mode 100644 index 00000000000..f13a2ae9d66 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/ecb/ecb_done.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file ecb_done.c + ECB implementation, finish chain, Tom St Denis +*/ + +#ifdef LTC_ECB_MODE + +/** Terminate the chain + @param ecb The ECB chain to terminate + @return CRYPT_OK on success +*/ +int ecb_done(symmetric_ECB *ecb) +{ + int err; + LTC_ARGCHK(ecb != NULL); + + if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) { + return err; + } + cipher_descriptor[ecb->cipher].done(&ecb->key); + return CRYPT_OK; +} + + + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/ecb/ecb_done.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/ecb/ecb_encrypt.c b/core/lib/libtomcrypt/src/modes/ecb/ecb_encrypt.c new file mode 100644 index 00000000000..d851c6165fd --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/ecb/ecb_encrypt.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file ecb_encrypt.c + ECB implementation, encrypt a block, Tom St Denis +*/ + +#ifdef LTC_ECB_MODE + +/** + ECB encrypt + @param pt Plaintext + @param ct [out] Ciphertext + @param len The number of octets to process (must be multiple of the cipher block size) + @param ecb ECB state + @return CRYPT_OK if successful +*/ +int ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_ECB *ecb) +{ + int err; + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(ecb != NULL); + if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) { + return err; + } + if (len % cipher_descriptor[ecb->cipher].block_length) { + return CRYPT_INVALID_ARG; + } + + /* check for accel */ + if (cipher_descriptor[ecb->cipher].accel_ecb_encrypt != NULL) { + return cipher_descriptor[ecb->cipher].accel_ecb_encrypt(pt, ct, len / cipher_descriptor[ecb->cipher].block_length, &ecb->key); + } else { + while (len) { + if ((err = cipher_descriptor[ecb->cipher].ecb_encrypt(pt, ct, &ecb->key)) != CRYPT_OK) { + return err; + } + pt += cipher_descriptor[ecb->cipher].block_length; + ct += cipher_descriptor[ecb->cipher].block_length; + len -= cipher_descriptor[ecb->cipher].block_length; + } + } + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/ecb/ecb_encrypt.c,v $ */ +/* $Revision: 1.10 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/ecb/ecb_start.c b/core/lib/libtomcrypt/src/modes/ecb/ecb_start.c new file mode 100644 index 00000000000..2218d8c6bbf --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/ecb/ecb_start.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file ecb_start.c + ECB implementation, start chain, Tom St Denis +*/ + + +#ifdef LTC_ECB_MODE + +/** + Initialize a ECB context + @param cipher The index of the cipher desired + @param key The secret key + @param keylen The length of the secret key (octets) + @param num_rounds Number of rounds in the cipher desired (0 for default) + @param ecb The ECB state to initialize + @return CRYPT_OK if successful +*/ +int ecb_start(int cipher, const unsigned char *key, int keylen, int num_rounds, symmetric_ECB *ecb) +{ + int err; + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ecb != NULL); + + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + ecb->cipher = cipher; + ecb->blocklen = cipher_descriptor[cipher].block_length; + return cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ecb->key); +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/ecb/ecb_start.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/ecb/sub.mk b/core/lib/libtomcrypt/src/modes/ecb/sub.mk new file mode 100644 index 00000000000..c47c061e69e --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/ecb/sub.mk @@ -0,0 +1,4 @@ +srcs-y += ecb_decrypt.c +srcs-y += ecb_done.c +srcs-y += ecb_encrypt.c +srcs-y += ecb_start.c diff --git a/core/lib/libtomcrypt/src/modes/f8/f8_decrypt.c b/core/lib/libtomcrypt/src/modes/f8/f8_decrypt.c new file mode 100644 index 00000000000..2f4591f8a41 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/f8/f8_decrypt.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file f8_decrypt.c + F8 implementation, decrypt data, Tom St Denis +*/ + +#ifdef LTC_F8_MODE + +/** + F8 decrypt + @param ct Ciphertext + @param pt [out] Plaintext + @param len Length of ciphertext (octets) + @param f8 F8 state + @return CRYPT_OK if successful +*/ +int f8_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_F8 *f8) +{ + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(f8 != NULL); + return f8_encrypt(ct, pt, len, f8); +} + + +#endif + + + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/f8/f8_decrypt.c,v $ */ +/* $Revision: 1.3 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/f8/f8_done.c b/core/lib/libtomcrypt/src/modes/f8/f8_done.c new file mode 100644 index 00000000000..91b5ddc9d3b --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/f8/f8_done.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file f8_done.c + F8 implementation, finish chain, Tom St Denis +*/ + +#ifdef LTC_F8_MODE + +/** Terminate the chain + @param f8 The F8 chain to terminate + @return CRYPT_OK on success +*/ +int f8_done(symmetric_F8 *f8) +{ + int err; + LTC_ARGCHK(f8 != NULL); + + if ((err = cipher_is_valid(f8->cipher)) != CRYPT_OK) { + return err; + } + cipher_descriptor[f8->cipher].done(&f8->key); + return CRYPT_OK; +} + + + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/f8/f8_done.c,v $ */ +/* $Revision: 1.3 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/f8/f8_encrypt.c b/core/lib/libtomcrypt/src/modes/f8/f8_encrypt.c new file mode 100644 index 00000000000..7a0039cbf6e --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/f8/f8_encrypt.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file f8_encrypt.c + F8 implementation, encrypt data, Tom St Denis +*/ + +#ifdef LTC_F8_MODE + +/** + F8 encrypt + @param pt Plaintext + @param ct [out] Ciphertext + @param len Length of plaintext (octets) + @param f8 F8 state + @return CRYPT_OK if successful +*/ +int f8_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_F8 *f8) +{ + int err, x; + unsigned char buf[MAXBLOCKSIZE]; + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(f8 != NULL); + if ((err = cipher_is_valid(f8->cipher)) != CRYPT_OK) { + return err; + } + + /* is blocklen/padlen valid? */ + if (f8->blocklen < 0 || f8->blocklen > (int)sizeof(f8->IV) || + f8->padlen < 0 || f8->padlen > (int)sizeof(f8->IV)) { + return CRYPT_INVALID_ARG; + } + + zeromem(buf, sizeof(buf)); + + /* make sure the pad is empty */ + if (f8->padlen == f8->blocklen) { + /* xor of IV, MIV and blockcnt == what goes into cipher */ + STORE32H(f8->blockcnt, (buf+(f8->blocklen-4))); + ++(f8->blockcnt); + for (x = 0; x < f8->blocklen; x++) { + f8->IV[x] ^= f8->MIV[x] ^ buf[x]; + } + if ((err = cipher_descriptor[f8->cipher].ecb_encrypt(f8->IV, f8->IV, &f8->key)) != CRYPT_OK) { + return err; + } + f8->padlen = 0; + } + +#ifdef LTC_FAST + if (f8->padlen == 0) { + while (len >= (unsigned long)f8->blocklen) { + STORE32H(f8->blockcnt, (buf+(f8->blocklen-4))); + ++(f8->blockcnt); + for (x = 0; x < f8->blocklen; x += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE*)(&ct[x])) = *((LTC_FAST_TYPE*)(&pt[x])) ^ *((LTC_FAST_TYPE*)(&f8->IV[x])); + *((LTC_FAST_TYPE*)(&f8->IV[x])) ^= *((LTC_FAST_TYPE*)(&f8->MIV[x])) ^ *((LTC_FAST_TYPE*)(&buf[x])); + } + if ((err = cipher_descriptor[f8->cipher].ecb_encrypt(f8->IV, f8->IV, &f8->key)) != CRYPT_OK) { + return err; + } + len -= x; + pt += x; + ct += x; + } + } +#endif + + while (len > 0) { + if (f8->padlen == f8->blocklen) { + /* xor of IV, MIV and blockcnt == what goes into cipher */ + STORE32H(f8->blockcnt, (buf+(f8->blocklen-4))); + ++(f8->blockcnt); + for (x = 0; x < f8->blocklen; x++) { + f8->IV[x] ^= f8->MIV[x] ^ buf[x]; + } + if ((err = cipher_descriptor[f8->cipher].ecb_encrypt(f8->IV, f8->IV, &f8->key)) != CRYPT_OK) { + return err; + } + f8->padlen = 0; + } + *ct++ = *pt++ ^ f8->IV[f8->padlen++]; + --len; + } + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/f8/f8_encrypt.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/f8/f8_getiv.c b/core/lib/libtomcrypt/src/modes/f8/f8_getiv.c new file mode 100644 index 00000000000..425a4209851 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/f8/f8_getiv.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file ofb_getiv.c + F8 implementation, get IV, Tom St Denis +*/ + +#ifdef LTC_F8_MODE + +/** + Get the current initial vector + @param IV [out] The destination of the initial vector + @param len [in/out] The max size and resulting size of the initial vector + @param f8 The F8 state + @return CRYPT_OK if successful +*/ +int f8_getiv(unsigned char *IV, unsigned long *len, symmetric_F8 *f8) +{ + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(len != NULL); + LTC_ARGCHK(f8 != NULL); + if ((unsigned long)f8->blocklen > *len) { + *len = f8->blocklen; + return CRYPT_BUFFER_OVERFLOW; + } + XMEMCPY(IV, f8->IV, f8->blocklen); + *len = f8->blocklen; + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/f8/f8_getiv.c,v $ */ +/* $Revision: 1.3 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/f8/f8_setiv.c b/core/lib/libtomcrypt/src/modes/f8/f8_setiv.c new file mode 100644 index 00000000000..b0bce2a90e7 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/f8/f8_setiv.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file f8_setiv.c + F8 implementation, set IV, Tom St Denis +*/ + +#ifdef LTC_F8_MODE + +/** + Set an initial vector + @param IV The initial vector + @param len The length of the vector (in octets) + @param f8 The F8 state + @return CRYPT_OK if successful +*/ +int f8_setiv(const unsigned char *IV, unsigned long len, symmetric_F8 *f8) +{ + int err; + + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(f8 != NULL); + + if ((err = cipher_is_valid(f8->cipher)) != CRYPT_OK) { + return err; + } + + if (len != (unsigned long)f8->blocklen) { + return CRYPT_INVALID_ARG; + } + + /* force next block */ + f8->padlen = 0; + return cipher_descriptor[f8->cipher].ecb_encrypt(IV, f8->IV, &f8->key); +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/f8/f8_setiv.c,v $ */ +/* $Revision: 1.3 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/f8/f8_start.c b/core/lib/libtomcrypt/src/modes/f8/f8_start.c new file mode 100644 index 00000000000..d7296e74577 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/f8/f8_start.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file f8_start.c + F8 implementation, start chain, Tom St Denis +*/ + + +#ifdef LTC_F8_MODE + +/** + Initialize an F8 context + @param cipher The index of the cipher desired + @param IV The initial vector + @param key The secret key + @param keylen The length of the secret key (octets) + @param salt_key The salting key for the IV + @param skeylen The length of the salting key (octets) + @param num_rounds Number of rounds in the cipher desired (0 for default) + @param f8 The F8 state to initialize + @return CRYPT_OK if successful +*/ +int f8_start( int cipher, const unsigned char *IV, + const unsigned char *key, int keylen, + const unsigned char *salt_key, int skeylen, + int num_rounds, symmetric_F8 *f8) +{ + int x, err; + unsigned char tkey[MAXBLOCKSIZE]; + + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(salt_key != NULL); + LTC_ARGCHK(f8 != NULL); + + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + +#ifdef LTC_FAST + if (cipher_descriptor[cipher].block_length % sizeof(LTC_FAST_TYPE)) { + return CRYPT_INVALID_ARG; + } +#endif + + /* copy details */ + f8->blockcnt = 0; + f8->cipher = cipher; + f8->blocklen = cipher_descriptor[cipher].block_length; + f8->padlen = f8->blocklen; + + /* now get key ^ salt_key [extend salt_ket with 0x55 as required to match length] */ + zeromem(tkey, sizeof(tkey)); + for (x = 0; x < keylen && x < (int)sizeof(tkey); x++) { + tkey[x] = key[x]; + } + for (x = 0; x < skeylen && x < (int)sizeof(tkey); x++) { + tkey[x] ^= salt_key[x]; + } + for (; x < keylen && x < (int)sizeof(tkey); x++) { + tkey[x] ^= 0x55; + } + + /* now encrypt with tkey[0..keylen-1] the IV and use that as the IV */ + if ((err = cipher_descriptor[cipher].setup(tkey, keylen, num_rounds, &f8->key)) != CRYPT_OK) { + return err; + } + + /* encrypt IV */ + if ((err = cipher_descriptor[f8->cipher].ecb_encrypt(IV, f8->MIV, &f8->key)) != CRYPT_OK) { + cipher_descriptor[f8->cipher].done(&f8->key); + return err; + } + zeromem(tkey, sizeof(tkey)); + zeromem(f8->IV, sizeof(f8->IV)); + + /* terminate this cipher */ + cipher_descriptor[f8->cipher].done(&f8->key); + + /* init the cipher */ + return cipher_descriptor[cipher].setup(key, keylen, num_rounds, &f8->key); +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/f8/f8_start.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/f8/f8_test_mode.c b/core/lib/libtomcrypt/src/modes/f8/f8_test_mode.c new file mode 100644 index 00000000000..81b3fd0469b --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/f8/f8_test_mode.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file f8_test_mode.c + F8 implementation, test, Tom St Denis +*/ + + +#ifdef LTC_F8_MODE + +int f8_test_mode(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const unsigned char key[16] = { 0x23, 0x48, 0x29, 0x00, 0x84, 0x67, 0xbe, 0x18, + 0x6c, 0x3d, 0xe1, 0x4a, 0xae, 0x72, 0xd6, 0x2c }; + static const unsigned char salt[4] = { 0x32, 0xf2, 0x87, 0x0d }; + static const unsigned char IV[16] = { 0x00, 0x6e, 0x5c, 0xba, 0x50, 0x68, 0x1d, 0xe5, + 0x5c, 0x62, 0x15, 0x99, 0xd4, 0x62, 0x56, 0x4a }; + static const unsigned char pt[39] = { 0x70, 0x73, 0x65, 0x75, 0x64, 0x6f, 0x72, 0x61, + 0x6e, 0x64, 0x6f, 0x6d, 0x6e, 0x65, 0x73, 0x73, + 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x6e, 0x65, 0x78, 0x74, 0x20, 0x62, 0x65, 0x73, + 0x74, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67 }; + static const unsigned char ct[39] = { 0x01, 0x9c, 0xe7, 0xa2, 0x6e, 0x78, 0x54, 0x01, + 0x4a, 0x63, 0x66, 0xaa, 0x95, 0xd4, 0xee, 0xfd, + 0x1a, 0xd4, 0x17, 0x2a, 0x14, 0xf9, 0xfa, 0xf4, + 0x55, 0xb7, 0xf1, 0xd4, 0xb6, 0x2b, 0xd0, 0x8f, + 0x56, 0x2c, 0x0e, 0xef, 0x7c, 0x48, 0x02 }; + unsigned char buf[39]; + symmetric_F8 f8; + int err, idx; + + idx = find_cipher("aes"); + if (idx == -1) { + idx = find_cipher("rijndael"); + if (idx == -1) return CRYPT_NOP; + } + + /* initialize the context */ + if ((err = f8_start(idx, IV, key, sizeof(key), salt, sizeof(salt), 0, &f8)) != CRYPT_OK) { + return err; + } + + /* encrypt block */ + if ((err = f8_encrypt(pt, buf, sizeof(pt), &f8)) != CRYPT_OK) { + f8_done(&f8); + return err; + } + f8_done(&f8); + + /* compare */ + if (XMEMCMP(buf, ct, sizeof(ct))) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/f8/f8_test_mode.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/f8/sub.mk b/core/lib/libtomcrypt/src/modes/f8/sub.mk new file mode 100644 index 00000000000..c50b5f96cc2 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/f8/sub.mk @@ -0,0 +1,7 @@ +srcs-y += f8_decrypt.c +srcs-y += f8_done.c +srcs-y += f8_encrypt.c +srcs-y += f8_getiv.c +srcs-y += f8_setiv.c +srcs-y += f8_start.c +srcs-y += f8_test_mode.c diff --git a/core/lib/libtomcrypt/src/modes/lrw/lrw_decrypt.c b/core/lib/libtomcrypt/src/modes/lrw/lrw_decrypt.c new file mode 100644 index 00000000000..be7447d19bd --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/lrw/lrw_decrypt.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file lrw_decrypt.c + LRW_MODE implementation, Decrypt blocks, Tom St Denis +*/ + +#ifdef LTC_LRW_MODE + +/** + LRW decrypt blocks + @param ct The ciphertext + @param pt [out] The plaintext + @param len The length in octets, must be a multiple of 16 + @param lrw The LRW state +*/ +int lrw_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_LRW *lrw) +{ + int err; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(lrw != NULL); + + if ((err = cipher_is_valid(lrw->cipher)) != CRYPT_OK) { + return err; + } + + if (cipher_descriptor[lrw->cipher].accel_lrw_decrypt != NULL) { + return cipher_descriptor[lrw->cipher].accel_lrw_decrypt(ct, pt, len, lrw->IV, lrw->tweak, &lrw->key); + } + + return lrw_process(ct, pt, len, LRW_DECRYPT, lrw); +} + + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/lrw/lrw_decrypt.c,v $ */ +/* $Revision: 1.9 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/lrw/lrw_done.c b/core/lib/libtomcrypt/src/modes/lrw/lrw_done.c new file mode 100644 index 00000000000..0a44bad3265 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/lrw/lrw_done.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file lrw_done.c + LRW_MODE implementation, Free resources, Tom St Denis +*/ + +#ifdef LTC_LRW_MODE + +/** + Terminate a LRW state + @param lrw The state to terminate + @return CRYPT_OK if successful +*/ +int lrw_done(symmetric_LRW *lrw) +{ + int err; + + LTC_ARGCHK(lrw != NULL); + + if ((err = cipher_is_valid(lrw->cipher)) != CRYPT_OK) { + return err; + } + cipher_descriptor[lrw->cipher].done(&lrw->key); + + return CRYPT_OK; +} + +#endif +/* $Source: /cvs/libtom/libtomcrypt/src/modes/lrw/lrw_done.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/lrw/lrw_encrypt.c b/core/lib/libtomcrypt/src/modes/lrw/lrw_encrypt.c new file mode 100644 index 00000000000..0032aab385d --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/lrw/lrw_encrypt.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file lrw_encrypt.c + LRW_MODE implementation, Encrypt blocks, Tom St Denis +*/ + +#ifdef LTC_LRW_MODE + +/** + LRW encrypt blocks + @param pt The plaintext + @param ct [out] The ciphertext + @param len The length in octets, must be a multiple of 16 + @param lrw The LRW state +*/ +int lrw_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_LRW *lrw) +{ + int err; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(lrw != NULL); + + if ((err = cipher_is_valid(lrw->cipher)) != CRYPT_OK) { + return err; + } + + if (cipher_descriptor[lrw->cipher].accel_lrw_encrypt != NULL) { + return cipher_descriptor[lrw->cipher].accel_lrw_encrypt(pt, ct, len, lrw->IV, lrw->tweak, &lrw->key); + } + + return lrw_process(pt, ct, len, LRW_ENCRYPT, lrw); +} + + +#endif +/* $Source: /cvs/libtom/libtomcrypt/src/modes/lrw/lrw_encrypt.c,v $ */ +/* $Revision: 1.10 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/lrw/lrw_getiv.c b/core/lib/libtomcrypt/src/modes/lrw/lrw_getiv.c new file mode 100644 index 00000000000..0297b3cf90f --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/lrw/lrw_getiv.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file lrw_getiv.c + LRW_MODE implementation, Retrieve the current IV, Tom St Denis +*/ + +#ifdef LTC_LRW_MODE + +/** + Get the IV for LRW + @param IV [out] The IV, must be 16 octets + @param len Length ... must be at least 16 :-) + @param lrw The LRW state to read + @return CRYPT_OK if successful +*/ +int lrw_getiv(unsigned char *IV, unsigned long *len, symmetric_LRW *lrw) +{ + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(len != NULL); + LTC_ARGCHK(lrw != NULL); + if (*len < 16) { + *len = 16; + return CRYPT_BUFFER_OVERFLOW; + } + + XMEMCPY(IV, lrw->IV, 16); + *len = 16; + return CRYPT_OK; +} + +#endif +/* $Source: /cvs/libtom/libtomcrypt/src/modes/lrw/lrw_getiv.c,v $ */ +/* $Revision: 1.10 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/lrw/lrw_process.c b/core/lib/libtomcrypt/src/modes/lrw/lrw_process.c new file mode 100644 index 00000000000..a184e0da930 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/lrw/lrw_process.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file lrw_process.c + LRW_MODE implementation, Encrypt/decrypt blocks, Tom St Denis +*/ + +#ifdef LTC_LRW_MODE + +/** + Process blocks with LRW, since decrypt/encrypt are largely the same they share this code. + @param pt The "input" data + @param ct [out] The "output" data + @param len The length of the input, must be a multiple of 128-bits (16 octets) + @param mode LRW_ENCRYPT or LRW_DECRYPT + @param lrw The LRW state + @return CRYPT_OK if successful +*/ +int lrw_process(const unsigned char *pt, unsigned char *ct, unsigned long len, int mode, symmetric_LRW *lrw) +{ + unsigned char prod[16]; + int x, err; +#ifdef LRW_TABLES + int y; +#endif + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(lrw != NULL); + + if (len & 15) { + return CRYPT_INVALID_ARG; + } + + while (len) { + /* copy pad */ + XMEMCPY(prod, lrw->pad, 16); + + /* increment IV */ + for (x = 15; x >= 0; x--) { + lrw->IV[x] = (lrw->IV[x] + 1) & 255; + if (lrw->IV[x]) { + break; + } + } + + /* update pad */ +#ifdef LRW_TABLES + /* for each byte changed we undo it's affect on the pad then add the new product */ + for (; x < 16; x++) { +#ifdef LTC_FAST + for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE *)(lrw->pad + y)) ^= *((LTC_FAST_TYPE *)(&lrw->PC[x][lrw->IV[x]][y])) ^ *((LTC_FAST_TYPE *)(&lrw->PC[x][(lrw->IV[x]-1)&255][y])); + } +#else + for (y = 0; y < 16; y++) { + lrw->pad[y] ^= lrw->PC[x][lrw->IV[x]][y] ^ lrw->PC[x][(lrw->IV[x]-1)&255][y]; + } +#endif + } +#else + gcm_gf_mult(lrw->tweak, lrw->IV, lrw->pad); +#endif + + /* xor prod */ +#ifdef LTC_FAST + for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE *)(ct + x)) = *((LTC_FAST_TYPE *)(pt + x)) ^ *((LTC_FAST_TYPE *)(prod + x)); + } +#else + for (x = 0; x < 16; x++) { + ct[x] = pt[x] ^ prod[x]; + } +#endif + + /* send through cipher */ + if (mode == LRW_ENCRYPT) { + if ((err = cipher_descriptor[lrw->cipher].ecb_encrypt(ct, ct, &lrw->key)) != CRYPT_OK) { + return err; + } + } else { + if ((err = cipher_descriptor[lrw->cipher].ecb_decrypt(ct, ct, &lrw->key)) != CRYPT_OK) { + return err; + } + } + + /* xor prod */ +#ifdef LTC_FAST + for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE *)(ct + x)) = *((LTC_FAST_TYPE *)(ct + x)) ^ *((LTC_FAST_TYPE *)(prod + x)); + } +#else + for (x = 0; x < 16; x++) { + ct[x] = ct[x] ^ prod[x]; + } +#endif + + /* move to next */ + pt += 16; + ct += 16; + len -= 16; + } + + return CRYPT_OK; +} + +#endif +/* $Source: /cvs/libtom/libtomcrypt/src/modes/lrw/lrw_process.c,v $ */ +/* $Revision: 1.11 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/lrw/lrw_setiv.c b/core/lib/libtomcrypt/src/modes/lrw/lrw_setiv.c new file mode 100644 index 00000000000..cf9db22c627 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/lrw/lrw_setiv.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file lrw_setiv.c + LRW_MODE implementation, Set the current IV, Tom St Denis +*/ + +#ifdef LTC_LRW_MODE + +/** + Set the IV for LRW + @param IV The IV, must be 16 octets + @param len Length ... must be 16 :-) + @param lrw The LRW state to update + @return CRYPT_OK if successful +*/ +int lrw_setiv(const unsigned char *IV, unsigned long len, symmetric_LRW *lrw) +{ + int err; +#ifdef LRW_TABLES + unsigned char T[16]; + int x, y; +#endif + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(lrw != NULL); + + if (len != 16) { + return CRYPT_INVALID_ARG; + } + + if ((err = cipher_is_valid(lrw->cipher)) != CRYPT_OK) { + return err; + } + + /* copy the IV */ + XMEMCPY(lrw->IV, IV, 16); + + /* check if we have to actually do work */ + if (cipher_descriptor[lrw->cipher].accel_lrw_encrypt != NULL && cipher_descriptor[lrw->cipher].accel_lrw_decrypt != NULL) { + /* we have accelerators, let's bail since they don't use lrw->pad anyways */ + return CRYPT_OK; + } + +#ifdef LRW_TABLES + XMEMCPY(T, &lrw->PC[0][IV[0]][0], 16); + for (x = 1; x < 16; x++) { +#ifdef LTC_FAST + for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE *)(T + y)) ^= *((LTC_FAST_TYPE *)(&lrw->PC[x][IV[x]][y])); + } +#else + for (y = 0; y < 16; y++) { + T[y] ^= lrw->PC[x][IV[x]][y]; + } +#endif + } + XMEMCPY(lrw->pad, T, 16); +#else + gcm_gf_mult(lrw->tweak, IV, lrw->pad); +#endif + + return CRYPT_OK; +} + + +#endif +/* $Source: /cvs/libtom/libtomcrypt/src/modes/lrw/lrw_setiv.c,v $ */ +/* $Revision: 1.13 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/lrw/lrw_start.c b/core/lib/libtomcrypt/src/modes/lrw/lrw_start.c new file mode 100644 index 00000000000..20b0781ed18 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/lrw/lrw_start.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file lrw_start.c + LRW_MODE implementation, start mode, Tom St Denis +*/ + +#ifdef LTC_LRW_MODE + +/** + Initialize the LRW context + @param cipher The cipher desired, must be a 128-bit block cipher + @param IV The index value, must be 128-bits + @param key The cipher key + @param keylen The length of the cipher key in octets + @param tweak The tweak value (second key), must be 128-bits + @param num_rounds The number of rounds for the cipher (0 == default) + @param lrw [out] The LRW state + @return CRYPT_OK on success. +*/ +int lrw_start( int cipher, + const unsigned char *IV, + const unsigned char *key, int keylen, + const unsigned char *tweak, + int num_rounds, + symmetric_LRW *lrw) +{ + int err; +#ifdef LRW_TABLES + unsigned char B[16]; + int x, y, z, t; +#endif + + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(tweak != NULL); + LTC_ARGCHK(lrw != NULL); + +#ifdef LTC_FAST + if (16 % sizeof(LTC_FAST_TYPE)) { + return CRYPT_INVALID_ARG; + } +#endif + + /* is cipher valid? */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + if (cipher_descriptor[cipher].block_length != 16) { + return CRYPT_INVALID_CIPHER; + } + + /* schedule key */ + if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &lrw->key)) != CRYPT_OK) { + return err; + } + lrw->cipher = cipher; + + /* copy the IV and tweak */ + XMEMCPY(lrw->tweak, tweak, 16); + +#ifdef LRW_TABLES + /* setup tables */ + /* generate the first table as it has no shifting (from which we make the other tables) */ + zeromem(B, 16); + for (y = 0; y < 256; y++) { + B[0] = y; + gcm_gf_mult(tweak, B, &lrw->PC[0][y][0]); + } + + /* now generate the rest of the tables based the previous table */ + for (x = 1; x < 16; x++) { + for (y = 0; y < 256; y++) { + /* now shift it right by 8 bits */ + t = lrw->PC[x-1][y][15]; + for (z = 15; z > 0; z--) { + lrw->PC[x][y][z] = lrw->PC[x-1][y][z-1]; + } + lrw->PC[x][y][0] = gcm_shift_table[t<<1]; + lrw->PC[x][y][1] ^= gcm_shift_table[(t<<1)+1]; + } + } +#endif + + /* generate first pad */ + return lrw_setiv(IV, 16, lrw); +} + + +#endif +/* $Source: /cvs/libtom/libtomcrypt/src/modes/lrw/lrw_start.c,v $ */ +/* $Revision: 1.12 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/lrw/lrw_test.c b/core/lib/libtomcrypt/src/modes/lrw/lrw_test.c new file mode 100644 index 00000000000..3765f166219 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/lrw/lrw_test.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file lrw_test.c + LRW_MODE implementation, test LRW, Tom St Denis +*/ + +#ifdef LTC_LRW_MODE + +/** + Test LRW against specs + @return CRYPT_OK if goodly +*/ +int lrw_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + unsigned char key[16], tweak[16], IV[16], P[16], expected_tweak[16], C[16]; + } tests[] = { + +{ +{ 0x45, 0x62, 0xac, 0x25, 0xf8, 0x28, 0x17, 0x6d, 0x4c, 0x26, 0x84, 0x14, 0xb5, 0x68, 0x01, 0x85 }, +{ 0x25, 0x8e, 0x2a, 0x05, 0xe7, 0x3e, 0x9d, 0x03, 0xee, 0x5a, 0x83, 0x0c, 0xcc, 0x09, 0x4c, 0x87 }, +{ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, +{ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, +{ 0x25, 0x8e, 0x2a, 0x05, 0xe7, 0x3e, 0x9d, 0x03, 0xee, 0x5a, 0x83, 0x0c, 0xcc, 0x09, 0x4c, 0x87 }, +{ 0xf1, 0xb2, 0x73, 0xcd, 0x65, 0xa3, 0xdf, 0x5f, 0xe9, 0x5d, 0x48, 0x92, 0x54, 0x63, 0x4e, 0xb8 } +}, + +{ +{ 0x59, 0x70, 0x47, 0x14, 0xf5, 0x57, 0x47, 0x8c, 0xd7, 0x79, 0xe8, 0x0f, 0x54, 0x88, 0x79, 0x44 }, +{ 0x35, 0x23, 0xc2, 0xde, 0xc5, 0x69, 0x4f, 0xa8, 0x72, 0xa9, 0xac, 0xa7, 0x0b, 0x2b, 0xee, 0xbc }, +{ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, +{ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, +{ 0x1a, 0x91, 0xe1, 0x6f, 0x62, 0xb4, 0xa7, 0xd4, 0x39, 0x54, 0xd6, 0x53, 0x85, 0x95, 0xf7, 0x5e }, +{ 0x00, 0xc8, 0x2b, 0xae, 0x95, 0xbb, 0xcd, 0xe5, 0x27, 0x4f, 0x07, 0x69, 0xb2, 0x60, 0xe1, 0x36 }, +}, + +{ +{ 0x59, 0x70, 0x47, 0x14, 0xf5, 0x57, 0x47, 0x8c, 0xd7, 0x79, 0xe8, 0x0f, 0x54, 0x88, 0x79, 0x44 }, +{ 0x67, 0x53, 0xc9, 0x0c, 0xb7, 0xd8, 0xcd, 0xe5, 0x06, 0xa0, 0x47, 0x78, 0x1a, 0xad, 0x85, 0x11 }, +{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }, +{ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, +{ 0x1a, 0x91, 0xe1, 0x6f, 0x62, 0xb4, 0xa7, 0xd4, 0x39, 0x54, 0xd6, 0x53, 0x85, 0x95, 0xf7, 0x5e }, +{ 0x00, 0xc8, 0x2b, 0xae, 0x95, 0xbb, 0xcd, 0xe5, 0x27, 0x4f, 0x07, 0x69, 0xb2, 0x60, 0xe1, 0x36 }, +}, + +{ + +{ 0xd8, 0x2a, 0x91, 0x34, 0xb2, 0x6a, 0x56, 0x50, 0x30, 0xfe, 0x69, 0xe2, 0x37, 0x7f, 0x98, 0x47 }, +{ 0x4e, 0xb5, 0x5d, 0x31, 0x05, 0x97, 0x3a, 0x3f, 0x5e, 0x23, 0xda, 0xfb, 0x5a, 0x45, 0xd6, 0xc0 }, +{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 }, +{ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, +{ 0x18, 0xc9, 0x1f, 0x6d, 0x60, 0x1a, 0x1a, 0x37, 0x5d, 0x0b, 0x0e, 0xf7, 0x3a, 0xd5, 0x74, 0xc4 }, +{ 0x76, 0x32, 0x21, 0x83, 0xed, 0x8f, 0xf1, 0x82, 0xf9, 0x59, 0x62, 0x03, 0x69, 0x0e, 0x5e, 0x01 }, + +} +}; + + int idx, err, x; + symmetric_LRW lrw; + unsigned char buf[2][16]; + + idx = find_cipher("aes"); + if (idx == -1) { + idx = find_cipher("rijndael"); + if (idx == -1) { + return CRYPT_NOP; + } + } + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + /* schedule it */ + if ((err = lrw_start(idx, tests[x].IV, tests[x].key, 16, tests[x].tweak, 0, &lrw)) != CRYPT_OK) { + return err; + } + + /* check pad against expected tweak */ + if (XMEMCMP(tests[x].expected_tweak, lrw.pad, 16)) { + lrw_done(&lrw); + return CRYPT_FAIL_TESTVECTOR; + } + + /* process block */ + if ((err = lrw_encrypt(tests[x].P, buf[0], 16, &lrw)) != CRYPT_OK) { + lrw_done(&lrw); + return err; + } + + if (XMEMCMP(buf[0], tests[x].C, 16)) { + lrw_done(&lrw); + return CRYPT_FAIL_TESTVECTOR; + } + + /* process block */ + if ((err = lrw_setiv(tests[x].IV, 16, &lrw)) != CRYPT_OK) { + lrw_done(&lrw); + return err; + } + + if ((err = lrw_decrypt(buf[0], buf[1], 16, &lrw)) != CRYPT_OK) { + lrw_done(&lrw); + return err; + } + + if (XMEMCMP(buf[1], tests[x].P, 16)) { + lrw_done(&lrw); + return CRYPT_FAIL_TESTVECTOR; + } + if ((err = lrw_done(&lrw)) != CRYPT_OK) { + return err; + } + } + return CRYPT_OK; +#endif +} + +#endif + + + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/lrw/lrw_test.c,v $ */ +/* $Revision: 1.12 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/lrw/sub.mk b/core/lib/libtomcrypt/src/modes/lrw/sub.mk new file mode 100644 index 00000000000..45e3dfb6f70 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/lrw/sub.mk @@ -0,0 +1,8 @@ +srcs-y += lrw_decrypt.c +srcs-y += lrw_done.c +srcs-y += lrw_encrypt.c +srcs-y += lrw_getiv.c +srcs-y += lrw_process.c +srcs-y += lrw_setiv.c +srcs-y += lrw_start.c +srcs-y += lrw_test.c diff --git a/core/lib/libtomcrypt/src/modes/ofb/ofb_decrypt.c b/core/lib/libtomcrypt/src/modes/ofb/ofb_decrypt.c new file mode 100644 index 00000000000..d034bbef171 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/ofb/ofb_decrypt.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file ofb_decrypt.c + OFB implementation, decrypt data, Tom St Denis +*/ + +#ifdef LTC_OFB_MODE + +/** + OFB decrypt + @param ct Ciphertext + @param pt [out] Plaintext + @param len Length of ciphertext (octets) + @param ofb OFB state + @return CRYPT_OK if successful +*/ +int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb) +{ + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(ofb != NULL); + return ofb_encrypt(ct, pt, len, ofb); +} + + +#endif + + + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/ofb/ofb_decrypt.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/ofb/ofb_done.c b/core/lib/libtomcrypt/src/modes/ofb/ofb_done.c new file mode 100644 index 00000000000..72bfb09211d --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/ofb/ofb_done.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file ofb_done.c + OFB implementation, finish chain, Tom St Denis +*/ + +#ifdef LTC_OFB_MODE + +/** Terminate the chain + @param ofb The OFB chain to terminate + @return CRYPT_OK on success +*/ +int ofb_done(symmetric_OFB *ofb) +{ + int err; + LTC_ARGCHK(ofb != NULL); + + if ((err = cipher_is_valid(ofb->cipher)) != CRYPT_OK) { + return err; + } + cipher_descriptor[ofb->cipher].done(&ofb->key); + return CRYPT_OK; +} + + + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/ofb/ofb_done.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/ofb/ofb_encrypt.c b/core/lib/libtomcrypt/src/modes/ofb/ofb_encrypt.c new file mode 100644 index 00000000000..943d9ce9834 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/ofb/ofb_encrypt.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file ofb_encrypt.c + OFB implementation, encrypt data, Tom St Denis +*/ + +#ifdef LTC_OFB_MODE + +/** + OFB encrypt + @param pt Plaintext + @param ct [out] Ciphertext + @param len Length of plaintext (octets) + @param ofb OFB state + @return CRYPT_OK if successful +*/ +int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_OFB *ofb) +{ + int err; + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(ofb != NULL); + if ((err = cipher_is_valid(ofb->cipher)) != CRYPT_OK) { + return err; + } + + /* is blocklen/padlen valid? */ + if (ofb->blocklen < 0 || ofb->blocklen > (int)sizeof(ofb->IV) || + ofb->padlen < 0 || ofb->padlen > (int)sizeof(ofb->IV)) { + return CRYPT_INVALID_ARG; + } + + while (len-- > 0) { + if (ofb->padlen == ofb->blocklen) { + if ((err = cipher_descriptor[ofb->cipher].ecb_encrypt(ofb->IV, ofb->IV, &ofb->key)) != CRYPT_OK) { + return err; + } + ofb->padlen = 0; + } + *ct++ = *pt++ ^ ofb->IV[(ofb->padlen)++]; + } + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/ofb/ofb_encrypt.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/ofb/ofb_getiv.c b/core/lib/libtomcrypt/src/modes/ofb/ofb_getiv.c new file mode 100644 index 00000000000..ee2d73d33ec --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/ofb/ofb_getiv.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file ofb_getiv.c + OFB implementation, get IV, Tom St Denis +*/ + +#ifdef LTC_OFB_MODE + +/** + Get the current initial vector + @param IV [out] The destination of the initial vector + @param len [in/out] The max size and resulting size of the initial vector + @param ofb The OFB state + @return CRYPT_OK if successful +*/ +int ofb_getiv(unsigned char *IV, unsigned long *len, symmetric_OFB *ofb) +{ + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(len != NULL); + LTC_ARGCHK(ofb != NULL); + if ((unsigned long)ofb->blocklen > *len) { + *len = ofb->blocklen; + return CRYPT_BUFFER_OVERFLOW; + } + XMEMCPY(IV, ofb->IV, ofb->blocklen); + *len = ofb->blocklen; + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/ofb/ofb_getiv.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/ofb/ofb_setiv.c b/core/lib/libtomcrypt/src/modes/ofb/ofb_setiv.c new file mode 100644 index 00000000000..efb66c8188d --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/ofb/ofb_setiv.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file ofb_setiv.c + OFB implementation, set IV, Tom St Denis +*/ + +#ifdef LTC_OFB_MODE + +/** + Set an initial vector + @param IV The initial vector + @param len The length of the vector (in octets) + @param ofb The OFB state + @return CRYPT_OK if successful +*/ +int ofb_setiv(const unsigned char *IV, unsigned long len, symmetric_OFB *ofb) +{ + int err; + + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(ofb != NULL); + + if ((err = cipher_is_valid(ofb->cipher)) != CRYPT_OK) { + return err; + } + + if (len != (unsigned long)ofb->blocklen) { + return CRYPT_INVALID_ARG; + } + + /* force next block */ + ofb->padlen = 0; + return cipher_descriptor[ofb->cipher].ecb_encrypt(IV, ofb->IV, &ofb->key); +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/ofb/ofb_setiv.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/ofb/ofb_start.c b/core/lib/libtomcrypt/src/modes/ofb/ofb_start.c new file mode 100644 index 00000000000..9633614cef0 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/ofb/ofb_start.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file ofb_start.c + OFB implementation, start chain, Tom St Denis +*/ + + +#ifdef LTC_OFB_MODE + +/** + Initialize a OFB context + @param cipher The index of the cipher desired + @param IV The initial vector + @param key The secret key + @param keylen The length of the secret key (octets) + @param num_rounds Number of rounds in the cipher desired (0 for default) + @param ofb The OFB state to initialize + @return CRYPT_OK if successful +*/ +int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key, + int keylen, int num_rounds, symmetric_OFB *ofb) +{ + int x, err; + + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ofb != NULL); + + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + /* copy details */ + ofb->cipher = cipher; + ofb->blocklen = cipher_descriptor[cipher].block_length; + for (x = 0; x < ofb->blocklen; x++) { + ofb->IV[x] = IV[x]; + } + + /* init the cipher */ + ofb->padlen = ofb->blocklen; + return cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ofb->key); +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/ofb/ofb_start.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/modes/ofb/sub.mk b/core/lib/libtomcrypt/src/modes/ofb/sub.mk new file mode 100644 index 00000000000..f1fceeb9f2e --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/ofb/sub.mk @@ -0,0 +1,6 @@ +srcs-y += ofb_decrypt.c +srcs-y += ofb_done.c +srcs-y += ofb_encrypt.c +srcs-y += ofb_getiv.c +srcs-y += ofb_setiv.c +srcs-y += ofb_start.c diff --git a/core/lib/libtomcrypt/src/modes/sub.mk b/core/lib/libtomcrypt/src/modes/sub.mk new file mode 100644 index 00000000000..1d4647f8ad6 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/sub.mk @@ -0,0 +1,8 @@ +subdirs-y += cbc +subdirs-y += cfb +subdirs-y += ctr +subdirs-y += ecb +subdirs-y += f8 +subdirs-y += lrw +subdirs-y += ofb +subdirs-y += xts diff --git a/core/lib/libtomcrypt/src/modes/xts/sub.mk b/core/lib/libtomcrypt/src/modes/xts/sub.mk new file mode 100644 index 00000000000..7a754d1dc27 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/xts/sub.mk @@ -0,0 +1,6 @@ +srcs-y += xts_decrypt.c +srcs-y += xts_done.c +srcs-y += xts_encrypt.c +srcs-y += xts_init.c +srcs-y += xts_mult_x.c +srcs-y += xts_test.c diff --git a/core/lib/libtomcrypt/src/modes/xts/xts_decrypt.c b/core/lib/libtomcrypt/src/modes/xts/xts_decrypt.c new file mode 100644 index 00000000000..fe3411ccc86 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/xts/xts_decrypt.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects +*/ + +#ifdef LTC_XTS_MODE + +static int tweak_uncrypt(const unsigned char *C, unsigned char *P, unsigned char *T, symmetric_xts *xts) +{ + unsigned long x; + int err; + + /* tweak encrypt block i */ +#ifdef LTC_FAST + for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE*)&P[x]) = *((LTC_FAST_TYPE*)&C[x]) ^ *((LTC_FAST_TYPE*)&T[x]); + } +#else + for (x = 0; x < 16; x++) { + P[x] = C[x] ^ T[x]; + } +#endif + + err = cipher_descriptor[xts->cipher].ecb_decrypt(P, P, &xts->key1); + +#ifdef LTC_FAST + for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE*)&P[x]) ^= *((LTC_FAST_TYPE*)&T[x]); + } +#else + for (x = 0; x < 16; x++) { + P[x] = P[x] ^ T[x]; + } +#endif + + /* LFSR the tweak */ + xts_mult_x(T); + + return err; +} + +/** XTS Decryption + @param ct [in] Ciphertext + @param ptlen Length of plaintext (and ciphertext) + @param pt [out] Plaintext + @param tweak [in] The 128--bit encryption tweak (e.g. sector number) + @param xts The XTS structure + Returns CRYPT_OK upon success +*/int xts_decrypt( + const unsigned char *ct, unsigned long ptlen, + unsigned char *pt, + const unsigned char *tweak, + symmetric_xts *xts) +{ + unsigned char PP[16], CC[16], T[16]; + unsigned long i, m, mo, lim; + int err; + + /* check inputs */ + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(tweak != NULL); + LTC_ARGCHK(xts != NULL); + + /* check if valid */ + if ((err = cipher_is_valid(xts->cipher)) != CRYPT_OK) { + return err; + } + + /* get number of blocks */ + m = ptlen >> 4; + mo = ptlen & 15; + + /* must have at least one full block */ + if (m == 0) { + return CRYPT_INVALID_ARG; + } + + /* encrypt the tweak */ + if ((err = cipher_descriptor[xts->cipher].ecb_encrypt(tweak, T, &xts->key2)) != CRYPT_OK) { + return err; + } + + /* for i = 0 to m-2 do */ + if (mo == 0) { + lim = m; + } else { + lim = m - 1; + } + + for (i = 0; i < lim; i++) { + err = tweak_uncrypt(ct, pt, T, xts); + ct += 16; + pt += 16; + } + + /* if ptlen not divide 16 then */ + if (mo > 0) { + XMEMCPY(CC, T, 16); + xts_mult_x(CC); + + /* PP = tweak decrypt block m-1 */ + if ((err = tweak_uncrypt(ct, PP, CC, xts)) != CRYPT_OK) { + return err; + } + + /* Pm = first ptlen % 16 bytes of PP */ + for (i = 0; i < mo; i++) { + CC[i] = ct[16+i]; + pt[16+i] = PP[i]; + } + for (; i < 16; i++) { + CC[i] = PP[i]; + } + + /* Pm-1 = Tweak uncrypt CC */ + if ((err = tweak_uncrypt(CC, pt, T, xts)) != CRYPT_OK) { + return err; + } + } + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/xts/xts_decrypt.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2007/05/12 14:05:56 $ */ diff --git a/core/lib/libtomcrypt/src/modes/xts/xts_done.c b/core/lib/libtomcrypt/src/modes/xts/xts_done.c new file mode 100644 index 00000000000..bb13e32de77 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/xts/xts_done.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects +*/ + +#ifdef LTC_XTS_MODE + +/** Terminate XTS state + @param XTS The state to terminate +*/ +void xts_done(symmetric_xts *xts) +{ + LTC_ARGCHKVD(xts != NULL); + cipher_descriptor[xts->cipher].done(&xts->key1); + cipher_descriptor[xts->cipher].done(&xts->key2); +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/xts/xts_done.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2007/03/10 23:59:09 $ */ + diff --git a/core/lib/libtomcrypt/src/modes/xts/xts_encrypt.c b/core/lib/libtomcrypt/src/modes/xts/xts_encrypt.c new file mode 100644 index 00000000000..97288ce560e --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/xts/xts_encrypt.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects +*/ + +#ifdef LTC_XTS_MODE + +static int tweak_crypt(const unsigned char *P, unsigned char *C, unsigned char *T, symmetric_xts *xts) +{ + unsigned long x; + int err; + + /* tweak encrypt block i */ +#ifdef LTC_FAST + for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE*)&C[x]) = *((LTC_FAST_TYPE*)&P[x]) ^ *((LTC_FAST_TYPE*)&T[x]); + } +#else + for (x = 0; x < 16; x++) { + C[x] = P[x] ^ T[x]; + } +#endif + + if ((err = cipher_descriptor[xts->cipher].ecb_encrypt(C, C, &xts->key1)) != CRYPT_OK) { + return err; + } + +#ifdef LTC_FAST + for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE*)&C[x]) ^= *((LTC_FAST_TYPE*)&T[x]); + } +#else + for (x = 0; x < 16; x++) { + C[x] = C[x] ^ T[x]; + } +#endif + + /* LFSR the tweak */ + xts_mult_x(T); + + return CRYPT_OK; +} + +/** XTS Encryption + @param pt [in] Plaintext + @param ptlen Length of plaintext (and ciphertext) + @param ct [out] Ciphertext + @param tweak [in] The 128--bit encryption tweak (e.g. sector number) + @param xts The XTS structure + Returns CRYPT_OK upon success +*/ +int xts_encrypt( + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + const unsigned char *tweak, + symmetric_xts *xts) +{ + unsigned char PP[16], CC[16], T[16]; + unsigned long i, m, mo, lim; + int err; + + /* check inputs */ + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(tweak != NULL); + LTC_ARGCHK(xts != NULL); + + /* check if valid */ + if ((err = cipher_is_valid(xts->cipher)) != CRYPT_OK) { + return err; + } + + /* get number of blocks */ + m = ptlen >> 4; + mo = ptlen & 15; + + /* must have at least one full block */ + if (m == 0) { + return CRYPT_INVALID_ARG; + } + + /* encrypt the tweak */ + if ((err = cipher_descriptor[xts->cipher].ecb_encrypt(tweak, T, &xts->key2)) != CRYPT_OK) { + return err; + } + + /* for i = 0 to m-2 do */ + if (mo == 0) { + lim = m; + } else { + lim = m - 1; + } + + for (i = 0; i < lim; i++) { + err = tweak_crypt(pt, ct, T, xts); + ct += 16; + pt += 16; + } + + /* if ptlen not divide 16 then */ + if (mo > 0) { + /* CC = tweak encrypt block m-1 */ + if ((err = tweak_crypt(pt, CC, T, xts)) != CRYPT_OK) { + return err; + } + + /* Cm = first ptlen % 16 bytes of CC */ + for (i = 0; i < mo; i++) { + PP[i] = pt[16+i]; + ct[16+i] = CC[i]; + } + + for (; i < 16; i++) { + PP[i] = CC[i]; + } + + /* Cm-1 = Tweak encrypt PP */ + if ((err = tweak_crypt(PP, ct, T, xts)) != CRYPT_OK) { + return err; + } + } + + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/xts/xts_encrypt.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2007/05/12 14:05:56 $ */ diff --git a/core/lib/libtomcrypt/src/modes/xts/xts_init.c b/core/lib/libtomcrypt/src/modes/xts/xts_init.c new file mode 100644 index 00000000000..a871c82f075 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/xts/xts_init.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects +*/ + +#ifdef LTC_XTS_MODE + + +/** Start XTS mode + @param cipher The index of the cipher to use + @param key1 The encrypt key + @param key2 The tweak encrypt key + @param keylen The length of the keys (each) in octets + @param num_rounds The number of rounds for the cipher (0 == default) + @param xts [out] XTS structure + Returns CRYPT_OK upon success. +*/ +int xts_start( int cipher, + const unsigned char *key1, + const unsigned char *key2, + unsigned long keylen, + int num_rounds, + symmetric_xts *xts) +{ + int err; + + /* check inputs */ + LTC_ARGCHK(key1 != NULL); + LTC_ARGCHK(key2 != NULL); + LTC_ARGCHK(xts != NULL); + + /* check if valid */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + if (cipher_descriptor[cipher].block_length != 16) { + return CRYPT_INVALID_ARG; + } + + /* schedule the two ciphers */ + if ((err = cipher_descriptor[cipher].setup(key1, keylen, num_rounds, &xts->key1)) != CRYPT_OK) { + return err; + } + if ((err = cipher_descriptor[cipher].setup(key2, keylen, num_rounds, &xts->key2)) != CRYPT_OK) { + return err; + } + xts->cipher = cipher; + + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/xts/xts_init.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2007/03/10 23:59:09 $ */ diff --git a/core/lib/libtomcrypt/src/modes/xts/xts_mult_x.c b/core/lib/libtomcrypt/src/modes/xts/xts_mult_x.c new file mode 100644 index 00000000000..1c3478b1559 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/xts/xts_mult_x.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects +*/ + +#ifdef LTC_XTS_MODE + +/** multiply by x + @param I The value to multiply by x (LFSR shift) +*/ +void xts_mult_x(unsigned char *I) +{ + int x; + unsigned char t, tt; + + for (x = t = 0; x < 16; x++) { + tt = I[x] >> 7; + I[x] = ((I[x] << 1) | t) & 0xFF; + t = tt; + } + if (tt) { + I[0] ^= 0x87; + } +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/xts/xts_mult_x.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2007/03/10 23:59:09 $ */ diff --git a/core/lib/libtomcrypt/src/modes/xts/xts_test.c b/core/lib/libtomcrypt/src/modes/xts/xts_test.c new file mode 100644 index 00000000000..2a986373423 --- /dev/null +++ b/core/lib/libtomcrypt/src/modes/xts/xts_test.c @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +#ifdef LTC_XTS_MODE + +/** + Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects + Returns CRYPT_OK upon success. +*/ +int xts_test(void) +{ +#ifdef LTC_NO_TEST + return CRYPT_NOP; +#else + static const struct { + int keylen; + unsigned char key1[32]; + unsigned char key2[32]; + ulong64 seqnum; + unsigned long PTLEN; + unsigned char PTX[512], CTX[512]; + } tests[] = { + +/* #1 32 byte key, 32 byte PTX */ +{ + 32, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + 0, + 32, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x91,0x7c,0xf6,0x9e,0xbd,0x68,0xb2,0xec,0x9b,0x9f,0xe9,0xa3,0xea,0xdd,0xa6,0x92,0xcd,0x43,0xd2,0xf5,0x95,0x98,0xed,0x85,0x8c,0x02,0xc2,0x65,0x2f,0xbf,0x92,0x2e }, +}, + +/* #2, 32 byte key, 32 byte PTX */ +{ + 32, + { 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11 }, + { 0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22 }, + CONST64(0x3333333333), + 32, + { 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44 }, + { 0xc4,0x54,0x18,0x5e,0x6a,0x16,0x93,0x6e,0x39,0x33,0x40,0x38,0xac,0xef,0x83,0x8b,0xfb,0x18,0x6f,0xff,0x74,0x80,0xad,0xc4,0x28,0x93,0x82,0xec,0xd6,0xd3,0x94,0xf0 }, +}, + +/* #5 from xts.7, 32 byte key, 32 byte PTX */ +{ + 32, + { 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0 }, + { 0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0 }, + CONST64(0x123456789a), + 32, + { 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44 }, + { 0xb0,0x1f,0x86,0xf8,0xed,0xc1,0x86,0x37,0x06,0xfa,0x8a,0x42,0x53,0xe3,0x4f,0x28,0xaf,0x31,0x9d,0xe3,0x83,0x34,0x87,0x0f,0x4d,0xd1,0xf9,0x4c,0xbe,0x98,0x32,0xf1 }, +}, + +/* #4, 32 byte key, 512 byte PTX */ +{ + 32, + { 0x27,0x18,0x28,0x18,0x28,0x45,0x90,0x45,0x23,0x53,0x60,0x28,0x74,0x71,0x35,0x26 }, + { 0x31,0x41,0x59,0x26,0x53,0x58,0x97,0x93,0x23,0x84,0x62,0x64,0x33,0x83,0x27,0x95 }, + 0, + 512, + { +0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, +0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, +0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, +0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, +0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, +0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf, +0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, +0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff, +0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, +0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, +0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, +0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, +0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, +0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf, +0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, +0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff, + }, + { +0x27,0xa7,0x47,0x9b,0xef,0xa1,0xd4,0x76,0x48,0x9f,0x30,0x8c,0xd4,0xcf,0xa6,0xe2,0xa9,0x6e,0x4b,0xbe,0x32,0x08,0xff,0x25,0x28,0x7d,0xd3,0x81,0x96,0x16,0xe8,0x9c, +0xc7,0x8c,0xf7,0xf5,0xe5,0x43,0x44,0x5f,0x83,0x33,0xd8,0xfa,0x7f,0x56,0x00,0x00,0x05,0x27,0x9f,0xa5,0xd8,0xb5,0xe4,0xad,0x40,0xe7,0x36,0xdd,0xb4,0xd3,0x54,0x12, +0x32,0x80,0x63,0xfd,0x2a,0xab,0x53,0xe5,0xea,0x1e,0x0a,0x9f,0x33,0x25,0x00,0xa5,0xdf,0x94,0x87,0xd0,0x7a,0x5c,0x92,0xcc,0x51,0x2c,0x88,0x66,0xc7,0xe8,0x60,0xce, +0x93,0xfd,0xf1,0x66,0xa2,0x49,0x12,0xb4,0x22,0x97,0x61,0x46,0xae,0x20,0xce,0x84,0x6b,0xb7,0xdc,0x9b,0xa9,0x4a,0x76,0x7a,0xae,0xf2,0x0c,0x0d,0x61,0xad,0x02,0x65, +0x5e,0xa9,0x2d,0xc4,0xc4,0xe4,0x1a,0x89,0x52,0xc6,0x51,0xd3,0x31,0x74,0xbe,0x51,0xa1,0x0c,0x42,0x11,0x10,0xe6,0xd8,0x15,0x88,0xed,0xe8,0x21,0x03,0xa2,0x52,0xd8, +0xa7,0x50,0xe8,0x76,0x8d,0xef,0xff,0xed,0x91,0x22,0x81,0x0a,0xae,0xb9,0x9f,0x91,0x72,0xaf,0x82,0xb6,0x04,0xdc,0x4b,0x8e,0x51,0xbc,0xb0,0x82,0x35,0xa6,0xf4,0x34, +0x13,0x32,0xe4,0xca,0x60,0x48,0x2a,0x4b,0xa1,0xa0,0x3b,0x3e,0x65,0x00,0x8f,0xc5,0xda,0x76,0xb7,0x0b,0xf1,0x69,0x0d,0xb4,0xea,0xe2,0x9c,0x5f,0x1b,0xad,0xd0,0x3c, +0x5c,0xcf,0x2a,0x55,0xd7,0x05,0xdd,0xcd,0x86,0xd4,0x49,0x51,0x1c,0xeb,0x7e,0xc3,0x0b,0xf1,0x2b,0x1f,0xa3,0x5b,0x91,0x3f,0x9f,0x74,0x7a,0x8a,0xfd,0x1b,0x13,0x0e, +0x94,0xbf,0xf9,0x4e,0xff,0xd0,0x1a,0x91,0x73,0x5c,0xa1,0x72,0x6a,0xcd,0x0b,0x19,0x7c,0x4e,0x5b,0x03,0x39,0x36,0x97,0xe1,0x26,0x82,0x6f,0xb6,0xbb,0xde,0x8e,0xcc, +0x1e,0x08,0x29,0x85,0x16,0xe2,0xc9,0xed,0x03,0xff,0x3c,0x1b,0x78,0x60,0xf6,0xde,0x76,0xd4,0xce,0xcd,0x94,0xc8,0x11,0x98,0x55,0xef,0x52,0x97,0xca,0x67,0xe9,0xf3, +0xe7,0xff,0x72,0xb1,0xe9,0x97,0x85,0xca,0x0a,0x7e,0x77,0x20,0xc5,0xb3,0x6d,0xc6,0xd7,0x2c,0xac,0x95,0x74,0xc8,0xcb,0xbc,0x2f,0x80,0x1e,0x23,0xe5,0x6f,0xd3,0x44, +0xb0,0x7f,0x22,0x15,0x4b,0xeb,0xa0,0xf0,0x8c,0xe8,0x89,0x1e,0x64,0x3e,0xd9,0x95,0xc9,0x4d,0x9a,0x69,0xc9,0xf1,0xb5,0xf4,0x99,0x02,0x7a,0x78,0x57,0x2a,0xee,0xbd, +0x74,0xd2,0x0c,0xc3,0x98,0x81,0xc2,0x13,0xee,0x77,0x0b,0x10,0x10,0xe4,0xbe,0xa7,0x18,0x84,0x69,0x77,0xae,0x11,0x9f,0x7a,0x02,0x3a,0xb5,0x8c,0xca,0x0a,0xd7,0x52, +0xaf,0xe6,0x56,0xbb,0x3c,0x17,0x25,0x6a,0x9f,0x6e,0x9b,0xf1,0x9f,0xdd,0x5a,0x38,0xfc,0x82,0xbb,0xe8,0x72,0xc5,0x53,0x9e,0xdb,0x60,0x9e,0xf4,0xf7,0x9c,0x20,0x3e, +0xbb,0x14,0x0f,0x2e,0x58,0x3c,0xb2,0xad,0x15,0xb4,0xaa,0x5b,0x65,0x50,0x16,0xa8,0x44,0x92,0x77,0xdb,0xd4,0x77,0xef,0x2c,0x8d,0x6c,0x01,0x7d,0xb7,0x38,0xb1,0x8d, +0xeb,0x4a,0x42,0x7d,0x19,0x23,0xce,0x3f,0xf2,0x62,0x73,0x57,0x79,0xa4,0x18,0xf2,0x0a,0x28,0x2d,0xf9,0x20,0x14,0x7b,0xea,0xbe,0x42,0x1e,0xe5,0x31,0x9d,0x05,0x68, + } +}, + +/* #7, 32 byte key, 17 byte PTX */ +{ + 32, + { 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0 }, + { 0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0 }, + CONST64(0x123456789a), + 17, + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10 }, + { 0x6c,0x16,0x25,0xdb,0x46,0x71,0x52,0x2d,0x3d,0x75,0x99,0x60,0x1d,0xe7,0xca,0x09,0xed }, +}, + +/* #15, 32 byte key, 25 byte PTX */ +{ + 32, + { 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0 }, + { 0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0 }, + CONST64(0x123456789a), + 25, + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18 }, + { 0x8f,0x4d,0xcb,0xad,0x55,0x55,0x8d,0x7b,0x4e,0x01,0xd9,0x37,0x9c,0xd4,0xea,0x22,0xed,0xbf,0x9d,0xac,0xe4,0x5d,0x6f,0x6a,0x73 }, +}, + +/* #21, 32 byte key, 31 byte PTX */ +{ + 32, + { 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0 }, + { 0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0 }, + CONST64(0x123456789a), + 31, + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e }, + { 0xd0,0x5b,0xc0,0x90,0xa8,0xe0,0x4f,0x1b,0x3d,0x3e,0xcd,0xd5,0xba,0xec,0x0f,0xd4,0xed,0xbf,0x9d,0xac,0xe4,0x5d,0x6f,0x6a,0x73,0x06,0xe6,0x4b,0xe5,0xdd,0x82 }, +}, + +}; + unsigned char OUT[512], T[16]; + ulong64 seq; + symmetric_xts xts; + int i, err, idx; + + /* AES can be under rijndael or aes... try to find it */ + if ((idx = find_cipher("aes")) == -1) { + if ((idx = find_cipher("rijndael")) == -1) { + return CRYPT_NOP; + } + } + + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + err = xts_start(idx, tests[i].key1, tests[i].key2, tests[i].keylen/2, 0, &xts); + if (err != CRYPT_OK) { + return err; + } + + seq = tests[i].seqnum; + STORE64L(seq,T); + XMEMSET(T+8, 0, 8); + + err = xts_encrypt(tests[i].PTX, tests[i].PTLEN, OUT, T, &xts); + if (err != CRYPT_OK) { + xts_done(&xts); + return err; + } + + if (XMEMCMP(OUT, tests[i].CTX, tests[i].PTLEN)) { + xts_done(&xts); + return CRYPT_FAIL_TESTVECTOR; + } + + err = xts_decrypt(tests[i].CTX, tests[i].PTLEN, OUT, T, &xts); + if (err != CRYPT_OK) { + xts_done(&xts); + return err; + } + + if (XMEMCMP(OUT, tests[i].PTX, tests[i].PTLEN)) { + xts_done(&xts); + return CRYPT_FAIL_TESTVECTOR; + } + xts_done(&xts); + } + return CRYPT_OK; +#endif +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/modes/xts/xts_test.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2007/03/10 23:59:09 $ */ diff --git a/core/lib/libtomcrypt/src/mpa_desc.c b/core/lib/libtomcrypt/src/mpa_desc.c new file mode 100644 index 00000000000..ecd0d7c9ca4 --- /dev/null +++ b/core/lib/libtomcrypt/src/mpa_desc.c @@ -0,0 +1,644 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tomcrypt_mpa.h" +#include + +mpa_scratch_mem external_mem_pool; + +void init_mpa_tomcrypt(const mpa_scratch_mem pool) +{ + external_mem_pool = pool; +} + + +static int init(void **a) +{ + LTC_ARGCHK(a != NULL); + if (mpa_alloc_static_temp_var((mpanum *)a, external_mem_pool) == NULL) { + return CRYPT_MEM; + } + mpa_set_S32(*a, 0); + return CRYPT_OK; +} + +static void deinit(void *a) +{ + LTC_ARGCHKVD(a != NULL); + + mpa_free_static_temp_var((mpanum *) &a, NULL); +} + +static int neg(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + mpa_neg((mpanum)b, (const mpanum)a); + return CRYPT_OK; +} + +static int copy(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + mpa_copy((mpanum)b, (const mpanum)a); + return CRYPT_OK; +} + +static int init_copy(void **a, void *b) +{ + if (init(a) != CRYPT_OK) { + return CRYPT_MEM; + } + return copy(b, *a); +} + +/* ---- trivial ---- */ +static int set_int(void *a, unsigned long b) +{ + LTC_ARGCHK(a != NULL); + if (b > (unsigned long) UINT32_MAX) { + return CRYPT_INVALID_ARG; + } + mpa_set_word((mpanum) a, (mpa_word_t)b); + return CRYPT_OK; +} + +static unsigned long get_int(void *a) +{ + LTC_ARGCHK(a != NULL); + return mpa_get_word((mpanum)a); +} + +static unsigned long get_digit(void *a, int n) +{ + LTC_ARGCHK(a != NULL); + return __mpanum_get_word(n, (mpanum) a); +} + +static int get_digit_count(void *a) +{ + LTC_ARGCHK(a != NULL); + return __mpanum_size((mpanum) a); +} + +static int compare(void *a, void *b) +{ + int ret; + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + ret = mpa_cmp((const mpanum)a, (const mpanum)b); + if (ret < 0) { + return LTC_MP_LT; + } else if (ret > 0) { + return LTC_MP_GT; + } else { + return LTC_MP_EQ; + } +} + +static int compare_d(void *a, unsigned long b) +{ + int ret; + LTC_ARGCHK(a != NULL); + // this particular case must be handled separately... + if (b > (unsigned long) MPA_INT_MAX) { + mpanum tmp = (mpanum) a; + ret = (tmp->size <= 0 ? LTC_MP_LT : + tmp->size > 1 ? LTC_MP_GT : + tmp->d[0] < b ? LTC_MP_LT : + tmp->d[0] == b ? LTC_MP_EQ : LTC_MP_GT); + } else { + ret = mpa_cmp_short(((const mpanum)a), b); + } + if (ret < 0) { + return LTC_MP_LT; + } else if (ret > 0) { + return LTC_MP_GT; + } else { + return LTC_MP_EQ; + } +} + +static int count_bits(void *a) +{ + LTC_ARGCHK(a != NULL); + // mpa_highest_bit_index returns the index of the highest '1' bit starting at 0 + // so adding 1 to the result gives the wanted result + return mpa_highest_bit_index((const mpanum)a) + 1; +} + +static int count_lsb_bits(void *a) +{ + LTC_ARGCHK(a != NULL); + if (((mpanum)a)->size == 0) { + return 0; + } + int zero_limb_nbr = 0; + int zero_bit_nbr = 0; + const mpanum aa = (mpanum) a; + while (aa->d[zero_limb_nbr] == 0) { + ++zero_limb_nbr; + } + zero_bit_nbr = zero_limb_nbr * MPA_WORD_SIZE; + while (!mpa_get_bit(aa, zero_bit_nbr)) { + ++zero_bit_nbr; + } + + return zero_bit_nbr; +} + + +static int twoexpt(void *a, int n) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(n >= 0); + int i; + mpa_asize_t q; /* quotient of n div WORD_SIZE */ + mpa_asize_t r; /* remainder of n div WORD_SIZE */ + + r = n & (MPA_WORD_SIZE - 1); /* 0 <= r < WORD_SIZE */ + q = n >> MPA_LOG_OF_WORD_SIZE; /* 0 <= q */ + + if (((mpanum)a)->alloc < (q + 1)) { + return CRYPT_MEM; + } + ((mpanum)a)->size = q + 1; + for (i = 0; i < ((mpanum)a)->size; ++i) { + ((mpanum)a)->d[i] = 0; + } + ((mpanum)a)->d[q] = 1 << r; + return CRYPT_OK; +} + +/* ---- conversions ---- */ + +/* read ascii string */ +static int read_radix(void *a, const char *b, int radix) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + if (radix != 16) { + return CRYPT_ERROR; + } + mpa_set_str((mpanum)a, b); + return CRYPT_OK; +} + +/* write one */ +static int write_radix(void *a, char *b, int radix) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + if (mpa_get_str(b, MPA_STRING_MODE_HEX_UC, 0, (const mpanum) a) == 0) { + return CRYPT_MEM; + } + return CRYPT_OK; +} + +/* get size as unsigned char string */ +static unsigned long unsigned_size(void *a) +{ + unsigned long t; + LTC_ARGCHK(a != NULL); + t = count_bits(a); + if (mpa_cmp_short((const mpanum)a, 0) == 0) return 0; + return (t>>3) + ((t&7)?1:0); +} + +/* store */ +static int unsigned_write(void *a, unsigned char *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + size_t len = unsigned_size(a); + mpa_get_oct_str(b, &len, (const mpanum) a); + return CRYPT_OK; +} + +/* read */ +static int unsigned_read(void *a, unsigned char *b, unsigned long len) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + mpa_set_oct_str((mpanum) a, b, len, 0); + return CRYPT_OK; +} + +/* add */ +static int add(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + mpa_add((mpanum) c, (const mpanum) a, (const mpanum) b, external_mem_pool); + return CRYPT_OK; +} + +static int addi(void *a, unsigned long b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + if (b > (unsigned long) UINT32_MAX) { + return CRYPT_INVALID_ARG; + } + mpa_add_word((mpanum) c, (const mpanum) a, b, external_mem_pool); + return CRYPT_OK; +} + +/* sub */ +static int sub(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + mpa_sub((mpanum) c, (const mpanum) a, (const mpanum) b, external_mem_pool); + return CRYPT_OK; +} + +static int subi(void *a, unsigned long b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + if (b > (unsigned long) UINT32_MAX) { + return CRYPT_INVALID_ARG; + } + mpa_sub_word((mpanum) c, (const mpanum) a, b, external_mem_pool); + return CRYPT_OK; +} + +/* mul */ +static int mul(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + mpa_mul((mpanum) c, (const mpanum) a, (const mpanum) b, external_mem_pool); + return CRYPT_OK; +} + +static int muli(void *a, unsigned long b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + if (b > (unsigned long) UINT32_MAX) { + return CRYPT_INVALID_ARG; + } + mpa_mul_word((mpanum) c, (const mpanum) a, b, external_mem_pool); + return CRYPT_OK; +} + +/* sqr */ +static int sqr(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + mpa_mul((mpanum) b, (const mpanum) a, (const mpanum) a, external_mem_pool); + return CRYPT_OK; +} + +/* div */ +static int divide(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + mpa_div(c, d, (const mpanum) a, (const mpanum) b, external_mem_pool); + return CRYPT_OK; +} + +static int div_2(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + mpa_shift_right(b, a, 1); + return CRYPT_OK; +} + +/* modi */ +static int modi(void *a, unsigned long b, unsigned long *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + if (b > (unsigned long) UINT32_MAX) { + return CRYPT_INVALID_ARG; + } + int err; + void *tmp; + if ((err = init(&tmp)) != CRYPT_OK) { + return CRYPT_MEM; + } + + if (set_int(tmp, b) != CRYPT_OK) {goto err;} + if (divide(a, tmp, NULL, tmp) != CRYPT_OK) {goto err;} + + *c = get_int(tmp); + + err: + deinit(tmp); + return CRYPT_OK; +} + +/* gcd */ +static int gcd(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + mpa_gcd((mpanum) c, (const mpanum) a, (const mpanum) b, external_mem_pool); + return CRYPT_OK; +} + +/* lcm */ +static int lcm(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + void *tmp; + if (init(&tmp) != CRYPT_OK) { + return CRYPT_MEM; + } + + if (mul(a, b, tmp) != CRYPT_OK) {goto err;} + if (gcd(a, b, c) != CRYPT_OK) {goto err;} + + /* We use the following equality: gcd(a, b) * lcm(a, b) = a * b */ + if (divide(tmp, c, c, NULL) != CRYPT_OK) {goto err;} + err: + deinit(tmp); + return CRYPT_OK; +} + +static int mod(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + mpa_mod((mpanum) c, (const mpanum) a, (const mpanum) b, external_mem_pool); + if (mpa_cmp_short(c, 0) < 0) { + mpa_add(c, c, b, external_mem_pool); + } + return CRYPT_OK; +} + +#include "mpa_debug.h" +static int mulmod(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + LTC_ARGCHK(d != NULL); + void *tmpa, *tmpb; + + mp_init_multi(&tmpa, &tmpb, NULL); + + mod(a, c, tmpa); + mod(b, c, tmpb); + mpa_mul_mod((mpanum) d, (const mpanum) tmpa, (const mpanum) tmpb, (const mpanum) c, external_mem_pool); + mp_clear_multi(tmpa, tmpb, NULL); + return CRYPT_OK; +} + +static int sqrmod(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + return mulmod(a, a, b, c); +} + +/* invmod */ +static int invmod(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + LTC_ARGCHK(b != c); + mod(a, b, c); + if (mpa_inv_mod((mpanum) c, (const mpanum) c, (const mpanum) b, external_mem_pool) != 0) { + return CRYPT_ERROR; + } + + return CRYPT_OK; +} + +/* setup */ +static int montgomery_setup(void *a, void **b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + mpa_word_t len = mpa_fmm_context_size_in_U32(count_bits(a)); + *b = malloc(len * sizeof(mpa_word_t)); + if (*b == NULL) { + return CRYPT_MEM; + } + mpa_fmm_context_base * b_tmp = (mpa_fmm_context_base *) *b; + mpa_init_static_fmm_context(b_tmp, len); + mpa_compute_fmm_context((const mpanum) a, b_tmp->r_ptr, b_tmp->r2_ptr, &(b_tmp->n_inv), external_mem_pool); + return CRYPT_OK; +} + +/* get normalization value */ +static int montgomery_normalization(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + mpa_asize_t s; + s = __mpanum_size((mpanum) b); + twoexpt(a, s * MPA_WORD_SIZE); + mpa_mod((mpanum) a, (const mpanum) a, (const mpanum) b, external_mem_pool); + return CRYPT_OK; +} + +/* reduce */ +static int montgomery_reduce(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + mpanum tmp; + init((void **)&tmp); + // WARNING + // Workaround for a bug when a > b (a greater than the modulus) + if (compare(a, b) == LTC_MP_GT) { + mpa_mod((mpanum) a, (const mpanum) a, (const mpanum) b, external_mem_pool); + } + mpa_montgomery_mul(tmp, + (mpanum) a, + mpa_constant_one(), + (mpanum) b, + ((mpa_fmm_context) c)->n_inv, + external_mem_pool); + mpa_copy(a, tmp); + deinit(tmp); + return CRYPT_OK; +} + +/* clean up */ +static void montgomery_deinit(void *a) +{ + free(a); +} + +static int exptmod(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + LTC_ARGCHK(d != NULL); + void *c_mont; + montgomery_setup(c, &c_mont); + + void *d_tmp; + int memguard; + + memguard = (a == d || b == d); + + if (memguard) { + init(&d_tmp); + } else { + d_tmp = d; + } + + // WARNING !! + // Temporary fix, since ExpMod behaves badly when a > c + // (ie "a" is greater than the modulus) + mod(a, c, d_tmp); + + + mpa_exp_mod((mpanum) d, + (const mpanum) d_tmp, + (const mpanum) b, + (const mpanum) c, + ((mpa_fmm_context)c_mont)->r_ptr, + ((mpa_fmm_context)c_mont)->r2_ptr, + ((mpa_fmm_context)c_mont)->n_inv, + external_mem_pool); + montgomery_deinit(c_mont); + if (memguard) { + deinit(d_tmp); + } + return CRYPT_OK; +} + +static int isprime(void *a, int *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + *b = mpa_is_prob_prime((mpanum) a, 100, external_mem_pool) != 0 ? LTC_MP_YES : LTC_MP_NO; + return CRYPT_OK; +} + +ltc_math_descriptor ltc_mp = { + .name = "MPA", + .bits_per_digit = MPA_WORD_SIZE, + + .init = &init, + .init_copy = &init_copy, + .deinit = &deinit, + + .neg = &neg, + .copy = ©, + + .set_int = &set_int, + .get_int = &get_int, + .get_digit = &get_digit, + .get_digit_count = &get_digit_count, + .compare = &compare, + .compare_d = &compare_d, + .count_bits = &count_bits, + .count_lsb_bits = &count_lsb_bits, + .twoexpt = &twoexpt, + + .read_radix = &read_radix, + .write_radix = &write_radix, + .unsigned_size = &unsigned_size, + .unsigned_write = &unsigned_write, + .unsigned_read = &unsigned_read, + + .add = &add, + .addi = &addi, + .sub = &sub, + .subi = &subi, + .mul = &mul, + .muli = &muli, + .sqr = &sqr, + .mpdiv = ÷, + .div_2 = &div_2, + .modi = &modi, + .gcd = &gcd, + .lcm = &lcm, + + .mod = &mod, + .mulmod = &mulmod, + .sqrmod = &sqrmod, + .invmod = &invmod, + + .montgomery_setup = &montgomery_setup, + .montgomery_normalization = &montgomery_normalization, + .montgomery_reduce = &montgomery_reduce, + .montgomery_deinit = &montgomery_deinit, + + .exptmod = &exptmod, + .isprime = &isprime, + +#ifdef LTC_MECC +#ifdef LTC_MECC_FP + .ecc_ptmul = <c_ecc_fp_mulmod, +#else + .ecc_ptmul = <c_ecc_mulmod, +#endif /* LTC_MECC_FP */ + .ecc_ptadd = <c_ecc_projective_add_point, + .ecc_ptdbl = <c_ecc_projective_dbl_point, + .ecc_map = <c_ecc_map, +#ifdef LTC_ECC_SHAMIR +#ifdef LTC_MECC_FP + .ecc_mul2add = <c_ecc_fp_mul2add, +#else + .ecc_mul2add = <c_ecc_mul2add, +#endif /* LTC_MECC_FP */ +#else + .ltc_ecc_mul2add = NULL, +#endif /* LTC_ECC_SHAMIR */ +#else + .ecc_ptmul = NULL, + .ecc_ptadd = NULL, + .ecc_ptdbl = NULL, + .ecc_map = NULL, + .ecc_mul2add = NULL +#endif /* LTC_MECC */ + +#ifdef LTC_MRSA + .rsa_keygen = &rsa_make_key, + .rsa_me = &rsa_exptmod, +#else + .rsa_keygen = NULL, + .rsa_me = NULL +#endif + +}; + diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c b/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c new file mode 100644 index 00000000000..9d16d90c312 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_decode_bit_string.c + ASN.1 DER, encode a BIT STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store a BIT STRING + @param in The DER encoded BIT STRING + @param inlen The size of the DER BIT STRING + @param out [out] The array of bits stored (one per char) + @param outlen [in/out] The number of bits stored + @return CRYPT_OK if successful +*/ +int der_decode_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long dlen, blen, x, y; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* packet must be at least 4 bytes */ + if (inlen < 4) { + return CRYPT_INVALID_ARG; + } + + /* check for 0x03 */ + if ((in[0]&0x1F) != 0x03) { + return CRYPT_INVALID_PACKET; + } + + /* offset in the data */ + 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; + } + + /* is the data len too long or too short? */ + if ((dlen == 0) || (dlen + x > inlen)) { + return CRYPT_INVALID_PACKET; + } + + /* get padding count */ + blen = ((dlen - 1) << 3) - (in[x++] & 7); + + /* too many bits? */ + if (blen > *outlen) { + *outlen = blen; + return CRYPT_BUFFER_OVERFLOW; + } + + /* decode/store the bits */ + for (y = 0; y < blen; y++) { + out[y] = (in[x] & (1 << (7 - (y & 7)))) ? 1 : 0; + if ((y & 7) == 7) { + ++x; + } + } + + /* we done */ + *outlen = blen; + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c b/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c new file mode 100644 index 00000000000..1776fc02aa7 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_encode_bit_string.c + ASN.1 DER, encode a BIT STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store a BIT STRING + @param in The array of bits to store (one per char) + @param inlen The number of bits tostore + @param out [out] The destination for the DER encoded BIT STRING + @param outlen [in/out] The max size and resulting size of the DER BIT STRING + @return CRYPT_OK if successful +*/ +int der_encode_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long len, x, y; + unsigned char buf; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* avoid overflows */ + if ((err = der_length_bit_string(inlen, &len)) != CRYPT_OK) { + return err; + } + + if (len > *outlen) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + /* store header (include bit padding count in length) */ + x = 0; + y = (inlen >> 3) + ((inlen&7) ? 1 : 0) + 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); + } + + /* store number of zero padding bits */ + out[x++] = (unsigned char)((8 - inlen) & 7); + + /* store the bits in big endian format */ + for (y = buf = 0; y < inlen; y++) { + buf |= (in[y] ? 1 : 0) << (7 - (y & 7)); + if ((y & 7) == 7) { + out[x++] = buf; + buf = 0; + } + } + /* store last byte */ + if (inlen & 7) { + out[x++] = buf; + } + *outlen = x; + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c b/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c new file mode 100644 index 00000000000..39667162b2e --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_length_bit_string.c + ASN.1 DER, get length of BIT STRING, Tom St Denis +*/ + +#ifdef LTC_DER +/** + Gets length of DER encoding of BIT STRING + @param nbits The number of bits in the string to encode + @param outlen [out] The length of the DER encoding for the given string + @return CRYPT_OK if successful +*/ +int der_length_bit_string(unsigned long nbits, unsigned long *outlen) +{ + unsigned long nbytes; + 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; + } + + return CRYPT_OK; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c,v $ */ +/* $Revision: 1.3 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/bit/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/bit/sub.mk new file mode 100644 index 00000000000..2afd6f51c72 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/bit/sub.mk @@ -0,0 +1,3 @@ +srcs-y += der_decode_bit_string.c +srcs-y += der_encode_bit_string.c +srcs-y += der_length_bit_string.c diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c b/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c new file mode 100644 index 00000000000..7188413c9ac --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_decode_boolean.c + ASN.1 DER, decode a BOOLEAN, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Read a BOOLEAN + @param in The destination for the DER encoded BOOLEAN + @param inlen The size of the DER BOOLEAN + @param out [out] The boolean to decode + @return CRYPT_OK if successful +*/ +int der_decode_boolean(const unsigned char *in, unsigned long inlen, + int *out) +{ + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + + if (inlen != 3 || in[0] != 0x01 || in[1] != 0x01 || (in[2] != 0x00 && in[2] != 0xFF)) { + return CRYPT_INVALID_ARG; + } + + *out = (in[2]==0xFF) ? 1 : 0; + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c,v $ */ +/* $Revision: 1.2 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c b/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c new file mode 100644 index 00000000000..90bf24bb1d1 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_encode_boolean.c + ASN.1 DER, encode a BOOLEAN, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store a BOOLEAN + @param in The boolean to encode + @param out [out] The destination for the DER encoded BOOLEAN + @param outlen [in/out] The max size and resulting size of the DER BOOLEAN + @return CRYPT_OK if successful +*/ +int der_encode_boolean(int in, + unsigned char *out, unsigned long *outlen) +{ + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(out != NULL); + + if (*outlen < 3) { + *outlen = 3; + return CRYPT_BUFFER_OVERFLOW; + } + + *outlen = 3; + out[0] = 0x01; + out[1] = 0x01; + out[2] = in ? 0xFF : 0x00; + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c b/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c new file mode 100644 index 00000000000..3f677c5650b --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_length_boolean.c + ASN.1 DER, get length of a BOOLEAN, Tom St Denis +*/ + +#ifdef LTC_DER +/** + Gets length of DER encoding of a BOOLEAN + @param outlen [out] The length of the DER encoding + @return CRYPT_OK if successful +*/ +int der_length_boolean(unsigned long *outlen) +{ + LTC_ARGCHK(outlen != NULL); + *outlen = 3; + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c,v $ */ +/* $Revision: 1.3 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/boolean/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/boolean/sub.mk new file mode 100644 index 00000000000..37612493140 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/boolean/sub.mk @@ -0,0 +1,3 @@ +srcs-y += der_decode_boolean.c +srcs-y += der_encode_boolean.c +srcs-y += der_length_boolean.c diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c b/core/lib/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c new file mode 100644 index 00000000000..27e4044a96e --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_decode_choice.c + ASN.1 DER, decode a CHOICE, Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Decode a CHOICE + @param in The DER encoded input + @param inlen [in/out] The size of the input and resulting size of read type + @param list The list of items to decode + @param outlen The number of items in the list + @return CRYPT_OK on success +*/ +int der_decode_choice(const unsigned char *in, unsigned long *inlen, + ltc_asn1_list *list, unsigned long outlen) +{ + unsigned long size, x, z; + void *data; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen != NULL); + LTC_ARGCHK(list != NULL); + + /* get blk size */ + if (*inlen < 2) { + return CRYPT_INVALID_PACKET; + } + + /* set all of the "used" flags to zero */ + for (x = 0; x < outlen; x++) { + list[x].used = 0; + } + + /* now scan until we have a winner */ + for (x = 0; x < outlen; x++) { + size = list[x].size; + data = list[x].data; + + switch (list[x].type) { + case LTC_ASN1_INTEGER: + if (der_decode_integer(in, *inlen, data) == CRYPT_OK) { + if (der_length_integer(data, &z) == CRYPT_OK) { + list[x].used = 1; + *inlen = z; + return CRYPT_OK; + } + } + break; + + case LTC_ASN1_SHORT_INTEGER: + if (der_decode_short_integer(in, *inlen, data) == CRYPT_OK) { + if (der_length_short_integer(size, &z) == CRYPT_OK) { + list[x].used = 1; + *inlen = z; + return CRYPT_OK; + } + } + break; + + case LTC_ASN1_BIT_STRING: + if (der_decode_bit_string(in, *inlen, data, &size) == CRYPT_OK) { + if (der_length_bit_string(size, &z) == CRYPT_OK) { + list[x].used = 1; + list[x].size = size; + *inlen = z; + return CRYPT_OK; + } + } + break; + + case LTC_ASN1_OCTET_STRING: + if (der_decode_octet_string(in, *inlen, data, &size) == CRYPT_OK) { + if (der_length_octet_string(size, &z) == CRYPT_OK) { + list[x].used = 1; + list[x].size = size; + *inlen = z; + return CRYPT_OK; + } + } + break; + + case LTC_ASN1_NULL: + if (*inlen == 2 && in[x] == 0x05 && in[x+1] == 0x00) { + *inlen = 2; + list[x].used = 1; + return CRYPT_OK; + } + break; + + case LTC_ASN1_OBJECT_IDENTIFIER: + if (der_decode_object_identifier(in, *inlen, data, &size) == CRYPT_OK) { + if (der_length_object_identifier(data, size, &z) == CRYPT_OK) { + list[x].used = 1; + list[x].size = size; + *inlen = z; + return CRYPT_OK; + } + } + break; + + case LTC_ASN1_IA5_STRING: + if (der_decode_ia5_string(in, *inlen, data, &size) == CRYPT_OK) { + if (der_length_ia5_string(data, size, &z) == CRYPT_OK) { + list[x].used = 1; + list[x].size = size; + *inlen = z; + return CRYPT_OK; + } + } + break; + + + case LTC_ASN1_PRINTABLE_STRING: + if (der_decode_printable_string(in, *inlen, data, &size) == CRYPT_OK) { + if (der_length_printable_string(data, size, &z) == CRYPT_OK) { + list[x].used = 1; + list[x].size = size; + *inlen = z; + return CRYPT_OK; + } + } + break; + + case LTC_ASN1_UTF8_STRING: + if (der_decode_utf8_string(in, *inlen, data, &size) == CRYPT_OK) { + if (der_length_utf8_string(data, size, &z) == CRYPT_OK) { + list[x].used = 1; + list[x].size = size; + *inlen = z; + return CRYPT_OK; + } + } + break; + + case LTC_ASN1_UTCTIME: + z = *inlen; + if (der_decode_utctime(in, &z, data) == CRYPT_OK) { + list[x].used = 1; + *inlen = z; + return CRYPT_OK; + } + break; + + case LTC_ASN1_SET: + case LTC_ASN1_SETOF: + case LTC_ASN1_SEQUENCE: + if (der_decode_sequence(in, *inlen, data, size) == CRYPT_OK) { + if (der_length_sequence(data, size, &z) == CRYPT_OK) { + list[x].used = 1; + *inlen = z; + return CRYPT_OK; + } + } + break; + + default: + return CRYPT_INVALID_ARG; + } + } + + return CRYPT_INVALID_PACKET; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c,v $ */ +/* $Revision: 1.9 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/choice/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/choice/sub.mk new file mode 100644 index 00000000000..d3b95ec89e1 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/choice/sub.mk @@ -0,0 +1 @@ +srcs-y += der_decode_choice.c diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c b/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c new file mode 100644 index 00000000000..d1dc4681152 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_decode_ia5_string.c + ASN.1 DER, encode a IA5 STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store a IA5 STRING + @param in The DER encoded IA5 STRING + @param inlen The size of the DER IA5 STRING + @param out [out] The array of octets stored (one per char) + @param outlen [in/out] The number of octets stored + @return CRYPT_OK if successful +*/ +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; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* must have header at least */ + if (inlen < 2) { + return CRYPT_INVALID_PACKET; + } + + /* check for 0x16 */ + if ((in[0] & 0x1F) != 0x16) { + return CRYPT_INVALID_PACKET; + } + 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; + } + + /* is it too long? */ + if (len > *outlen) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + if (len + x > inlen) { + return CRYPT_INVALID_PACKET; + } + + /* read the data */ + for (y = 0; y < len; y++) { + t = der_ia5_value_decode(in[x++]); + if (t == -1) { + return CRYPT_INVALID_ARG; + } + out[y] = t; + } + + *outlen = y; + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c b/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c new file mode 100644 index 00000000000..17a63546171 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_encode_ia5_string.c + ASN.1 DER, encode a IA5 STRING, Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Store an IA5 STRING + @param in The array of IA5 to store (one per char) + @param inlen The number of IA5 to store + @param out [out] The destination for the DER encoded IA5 STRING + @param outlen [in/out] The max size and resulting size of the DER IA5 STRING + @return CRYPT_OK if successful +*/ +int der_encode_ia5_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); + LTC_ARGCHK(outlen != NULL); + + /* get the size */ + if ((err = der_length_ia5_string(in, inlen, &len)) != CRYPT_OK) { + return err; + } + + /* too big? */ + if (len > *outlen) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + /* 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; + } + + /* store octets */ + for (y = 0; y < inlen; y++) { + out[x++] = der_ia5_char_encode(in[y]); + } + + /* retun length */ + *outlen = x; + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c b/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c new file mode 100644 index 00000000000..7acea72b349 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_length_ia5_string.c + ASN.1 DER, get length of IA5 STRING, Tom St Denis +*/ + +#ifdef LTC_DER + +static const struct { + int code, value; +} ia5_table[] = { +{ '\0', 0 }, +{ '\a', 7 }, +{ '\b', 8 }, +{ '\t', 9 }, +{ '\n', 10 }, +{ '\f', 12 }, +{ '\r', 13 }, +{ ' ', 32 }, +{ '!', 33 }, +{ '"', 34 }, +{ '#', 35 }, +{ '$', 36 }, +{ '%', 37 }, +{ '&', 38 }, +{ '\'', 39 }, +{ '(', 40 }, +{ ')', 41 }, +{ '*', 42 }, +{ '+', 43 }, +{ ',', 44 }, +{ '-', 45 }, +{ '.', 46 }, +{ '/', 47 }, +{ '0', 48 }, +{ '1', 49 }, +{ '2', 50 }, +{ '3', 51 }, +{ '4', 52 }, +{ '5', 53 }, +{ '6', 54 }, +{ '7', 55 }, +{ '8', 56 }, +{ '9', 57 }, +{ ':', 58 }, +{ ';', 59 }, +{ '<', 60 }, +{ '=', 61 }, +{ '>', 62 }, +{ '?', 63 }, +{ '@', 64 }, +{ 'A', 65 }, +{ 'B', 66 }, +{ 'C', 67 }, +{ 'D', 68 }, +{ 'E', 69 }, +{ 'F', 70 }, +{ 'G', 71 }, +{ 'H', 72 }, +{ 'I', 73 }, +{ 'J', 74 }, +{ 'K', 75 }, +{ 'L', 76 }, +{ 'M', 77 }, +{ 'N', 78 }, +{ 'O', 79 }, +{ 'P', 80 }, +{ 'Q', 81 }, +{ 'R', 82 }, +{ 'S', 83 }, +{ 'T', 84 }, +{ 'U', 85 }, +{ 'V', 86 }, +{ 'W', 87 }, +{ 'X', 88 }, +{ 'Y', 89 }, +{ 'Z', 90 }, +{ '[', 91 }, +{ '\\', 92 }, +{ ']', 93 }, +{ '^', 94 }, +{ '_', 95 }, +{ '`', 96 }, +{ 'a', 97 }, +{ 'b', 98 }, +{ 'c', 99 }, +{ 'd', 100 }, +{ 'e', 101 }, +{ 'f', 102 }, +{ 'g', 103 }, +{ 'h', 104 }, +{ 'i', 105 }, +{ 'j', 106 }, +{ 'k', 107 }, +{ 'l', 108 }, +{ 'm', 109 }, +{ 'n', 110 }, +{ 'o', 111 }, +{ 'p', 112 }, +{ 'q', 113 }, +{ 'r', 114 }, +{ 's', 115 }, +{ 't', 116 }, +{ 'u', 117 }, +{ 'v', 118 }, +{ 'w', 119 }, +{ 'x', 120 }, +{ 'y', 121 }, +{ 'z', 122 }, +{ '{', 123 }, +{ '|', 124 }, +{ '}', 125 }, +{ '~', 126 } +}; + +int der_ia5_char_encode(int c) +{ + int x; + for (x = 0; x < (int)(sizeof(ia5_table)/sizeof(ia5_table[0])); x++) { + if (ia5_table[x].code == c) { + return ia5_table[x].value; + } + } + return -1; +} + +int der_ia5_value_decode(int v) +{ + int x; + for (x = 0; x < (int)(sizeof(ia5_table)/sizeof(ia5_table[0])); x++) { + if (ia5_table[x].value == v) { + return ia5_table[x].code; + } + } + return -1; +} + +/** + Gets length of DER encoding of IA5 STRING + @param octets The values you want to encode + @param noctets The number of octets in the string to encode + @param outlen [out] The length of the DER encoding for the given string + @return CRYPT_OK if successful +*/ +int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen) +{ + unsigned long x; + + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(octets != NULL); + + /* scan string for validity */ + for (x = 0; x < noctets; x++) { + if (der_ia5_char_encode(octets[x]) == -1) { + return CRYPT_INVALID_ARG; + } + } + + 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; + } + + return CRYPT_OK; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c,v $ */ +/* $Revision: 1.3 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/ia5/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/ia5/sub.mk new file mode 100644 index 00000000000..dc32a5d0e79 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/ia5/sub.mk @@ -0,0 +1,3 @@ +srcs-y += der_decode_ia5_string.c +srcs-y += der_encode_ia5_string.c +srcs-y += der_length_ia5_string.c diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c b/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c new file mode 100644 index 00000000000..195ba0fb249 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_decode_integer.c + ASN.1 DER, decode an integer, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Read a mp_int integer + @param in The DER encoded data + @param inlen Size of DER encoded data + @param num The first mp_int to decode + @return CRYPT_OK if successful +*/ +int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num) +{ + unsigned long x, y, z; + int err; + + LTC_ARGCHK(num != NULL); + LTC_ARGCHK(in != NULL); + + /* min DER INTEGER is 0x02 01 00 == 0 */ + if (inlen < (1 + 1 + 1)) { + return CRYPT_INVALID_PACKET; + } + + /* ok expect 0x02 when we AND with 0001 1111 [1F] */ + x = 0; + if ((in[x++] & 0x1F) != 0x02) { + 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; + } + + /* no so read it */ + if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, y)) != CRYPT_OK) { + return err; + } + } + + /* see if it's negative */ + if (in[x] & 0x80) { + void *tmp; + if (mp_init(&tmp) != CRYPT_OK) { + return CRYPT_MEM; + } + + if (mp_2expt(tmp, mp_count_bits(num)) != CRYPT_OK || mp_sub(num, tmp, num) != CRYPT_OK) { + mp_clear(tmp); + return CRYPT_MEM; + } + mp_clear(tmp); + } + + return CRYPT_OK; + +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c b/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c new file mode 100644 index 00000000000..0266d8c8c13 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_encode_integer.c + ASN.1 DER, encode an integer, Tom St Denis +*/ + + +#ifdef LTC_DER + +/* Exports a positive bignum as DER format (upto 2^32 bytes in size) */ +/** + Store a mp_int integer + @param num The first mp_int to encode + @param out [out] The destination for the DER encoded integers + @param outlen [in/out] The max size and resulting size of the DER encoded integers + @return CRYPT_OK if successful +*/ +int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen) +{ + unsigned long tmplen, y; + int err, leading_zero; + + LTC_ARGCHK(num != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* find out how big this will be */ + if ((err = der_length_integer(num, &tmplen)) != CRYPT_OK) { + return err; + } + + if (*outlen < tmplen) { + *outlen = tmplen; + return CRYPT_BUFFER_OVERFLOW; + } + + if (mp_cmp_d(num, 0) != LTC_MP_LT) { + /* we only need a leading zero if the msb of the first byte is one */ + if ((mp_count_bits(num) & 7) == 0 || mp_iszero(num) == LTC_MP_YES) { + leading_zero = 1; + } else { + leading_zero = 0; + } + + /* get length of num in bytes (plus 1 since we force the msbyte to zero) */ + y = mp_unsigned_bin_size(num) + leading_zero; + } else { + leading_zero = 0; + y = mp_count_bits(num); + y = y + (8 - (y & 7)); + y = y >> 3; + if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) --y; + } + /* 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; + } + + /* now store msbyte of zero if num is non-zero */ + if (leading_zero) { + *out++ = 0x00; + } + + /* if it's not zero store it as big endian */ + if (mp_cmp_d(num, 0) == LTC_MP_GT) { + err = mp_to_unsigned_bin(num, out); + /* now store the mpint */ + if (err != CRYPT_OK) { + return err; + } + } else if (mp_iszero(num) != LTC_MP_YES) { + void *tmp; + + /* negative */ + if (mp_init(&tmp) != CRYPT_OK) { + return CRYPT_MEM; + } + + /* 2^roundup and subtract */ + y = mp_count_bits(num); + y = y + (8 - (y & 7)); + if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) y -= 8; + if (mp_2expt(tmp, y) != CRYPT_OK || mp_add(tmp, num, tmp) != CRYPT_OK) { + mp_clear(tmp); + return CRYPT_MEM; + } + if ((err = mp_to_unsigned_bin(tmp, out)) != CRYPT_OK) { + mp_clear(tmp); + return err; + } + mp_clear(tmp); + } + + /* we good */ + *outlen = tmplen; + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c,v $ */ +/* $Revision: 1.9 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c b/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c new file mode 100644 index 00000000000..4b14ce06d8e --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_length_integer.c + ASN.1 DER, get length of encoding, Tom St Denis +*/ + + +#ifdef LTC_DER +/** + Gets length of DER encoding of num + @param num The int to get the size of + @param outlen [out] The length of the DER encoding for the given integer + @return CRYPT_OK if successful +*/ +int der_length_integer(void *num, unsigned long *outlen) +{ + unsigned long z, len; + int leading_zero; + + LTC_ARGCHK(num != NULL); + LTC_ARGCHK(outlen != NULL); + + if (mp_cmp_d(num, 0) != LTC_MP_LT) { + /* positive */ + + /* we only need a leading zero if the msb of the first byte is one */ + if ((mp_count_bits(num) & 7) == 0 || mp_iszero(num) == LTC_MP_YES) { + leading_zero = 1; + } else { + leading_zero = 0; + } + + /* size for bignum */ + z = 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 */ + leading_zero = 0; + 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; + } + + /* 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; + } + } + + /* we need a 0x02 to indicate it's INTEGER */ + ++len; + + /* return length */ + *outlen = len; + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/integer/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/integer/sub.mk new file mode 100644 index 00000000000..d319f91aaac --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/integer/sub.mk @@ -0,0 +1,3 @@ +srcs-y += der_decode_integer.c +srcs-y += der_encode_integer.c +srcs-y += der_length_integer.c diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c b/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c new file mode 100644 index 00000000000..13d5f1c269a --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_decode_object_identifier.c + ASN.1 DER, Decode Object Identifier, Tom St Denis +*/ + +#ifdef LTC_DER +/** + Decode OID data and store the array of integers in words + @param in The OID DER encoded data + @param inlen The length of the OID data + @param words [out] The destination of the OID words + @param outlen [in/out] The number of OID words + @return CRYPT_OK if successful +*/ +int der_decode_object_identifier(const unsigned char *in, unsigned long inlen, + unsigned long *words, unsigned long *outlen) +{ + unsigned long x, y, t, len; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(words != NULL); + LTC_ARGCHK(outlen != NULL); + + /* header is at least 3 bytes */ + if (inlen < 3) { + return CRYPT_INVALID_PACKET; + } + + /* must be room for at least two words */ + if (*outlen < 2) { + return CRYPT_BUFFER_OVERFLOW; + } + + /* decode the packet header */ + x = 0; + if ((in[x++] & 0x1F) != 0x06) { + 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++]; + } + } + + if (len < 1 || (len + x) > inlen) { + return CRYPT_INVALID_PACKET; + } + + /* decode words */ + y = 0; + t = 0; + while (len--) { + t = (t << 7) | (in[x] & 0x7F); + 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; + } else { + words[y++] = t; + } + t = 0; + } + } + + *outlen = y; + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c b/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c new file mode 100644 index 00000000000..890114d8bd3 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_encode_object_identifier.c + ASN.1 DER, Encode Object Identifier, Tom St Denis +*/ + +#ifdef LTC_DER +/** + Encode an OID + @param words The words to encode (upto 32-bits each) + @param nwords The number of words in the OID + @param out [out] Destination of OID data + @param outlen [in/out] The max and resulting size of the OID + @return CRYPT_OK if successful +*/ +int der_encode_object_identifier(unsigned long *words, unsigned long nwords, + unsigned char *out, unsigned long *outlen) +{ + unsigned long i, x, y, z, t, mask, wordbuf; + int err; + + LTC_ARGCHK(words != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* check length */ + if ((err = der_length_object_identifier(words, nwords, &x)) != CRYPT_OK) { + return err; + } + if (x > *outlen) { + *outlen = x; + return CRYPT_BUFFER_OVERFLOW; + } + + /* compute length to store OID data */ + z = 0; + wordbuf = words[0] * 40 + words[1]; + for (y = 1; y < nwords; y++) { + t = der_object_identifier_bits(wordbuf); + z += t/7 + ((t%7) ? 1 : 0) + (wordbuf == 0 ? 1 : 0); + if (y < nwords - 1) { + wordbuf = words[y + 1]; + } + } + + /* 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; + } + + /* store first byte */ + wordbuf = words[0] * 40 + words[1]; + for (i = 1; i < nwords; i++) { + /* store 7 bit words in little endian */ + t = wordbuf & 0xFFFFFFFF; + if (t) { + y = x; + mask = 0; + while (t) { + out[x++] = (unsigned char)((t & 0x7F) | mask); + t >>= 7; + mask |= 0x80; /* upper bit is set on all but the last byte */ + } + /* now swap bytes y...x-1 */ + z = x - 1; + while (y < z) { + t = out[y]; out[y] = out[z]; out[z] = (unsigned char)t; + ++y; + --z; + } + } else { + /* zero word */ + out[x++] = 0x00; + } + + if (i < nwords - 1) { + wordbuf = words[i + 1]; + } + } + + *outlen = x; + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c b/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c new file mode 100644 index 00000000000..d2fd0e0b452 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_length_object_identifier.c + ASN.1 DER, get length of Object Identifier, Tom St Denis +*/ + +#ifdef LTC_DER + +unsigned long der_object_identifier_bits(unsigned long x) +{ + unsigned long c; + x &= 0xFFFFFFFF; + c = 0; + while (x) { + ++c; + x >>= 1; + } + return c; +} + + +/** + Gets length of DER encoding of Object Identifier + @param nwords The number of OID words + @param words The actual OID words to get the size of + @param outlen [out] The length of the DER encoding for the given string + @return CRYPT_OK if successful +*/ +int der_length_object_identifier(unsigned long *words, unsigned long nwords, unsigned long *outlen) +{ + unsigned long y, z, t, wordbuf; + + LTC_ARGCHK(words != NULL); + LTC_ARGCHK(outlen != NULL); + + + /* must be >= 2 words */ + if (nwords < 2) { + return CRYPT_INVALID_ARG; + } + + /* word1 = 0,1,2,3 and word2 0..39 */ + if (words[0] > 3 || (words[0] < 2 && words[1] > 39)) { + return CRYPT_INVALID_ARG; + } + + /* leading word is the first two */ + z = 0; + wordbuf = words[0] * 40 + words[1]; + for (y = 1; y < nwords; y++) { + t = der_object_identifier_bits(wordbuf); + z += t/7 + ((t%7) ? 1 : 0) + (wordbuf == 0 ? 1 : 0); + if (y < nwords - 1) { + /* grab next word */ + wordbuf = words[y+1]; + } + } + + /* now depending on the length our length encoding changes */ + if (z < 128) { + z += 2; + } else if (z < 256) { + z += 3; + } else if (z < 65536UL) { + z += 4; + } else { + return CRYPT_INVALID_ARG; + } + + *outlen = z; + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/sub.mk new file mode 100644 index 00000000000..b56efb04287 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/sub.mk @@ -0,0 +1,3 @@ +srcs-y += der_decode_object_identifier.c +srcs-y += der_encode_object_identifier.c +srcs-y += der_length_object_identifier.c diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c b/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c new file mode 100644 index 00000000000..bae47606865 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_decode_octet_string.c + ASN.1 DER, encode a OCTET STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store a OCTET STRING + @param in The DER encoded OCTET STRING + @param inlen The size of the DER OCTET STRING + @param out [out] The array of octets stored (one per char) + @param outlen [in/out] The number of octets stored + @return CRYPT_OK if successful +*/ +int der_decode_octet_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y, len; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* must have header at least */ + if (inlen < 2) { + return CRYPT_INVALID_PACKET; + } + + /* check for 0x04 */ + if ((in[0] & 0x1F) != 0x04) { + return CRYPT_INVALID_PACKET; + } + 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; + } + + /* is it too long? */ + if (len > *outlen) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + if (len + x > inlen) { + return CRYPT_INVALID_PACKET; + } + + /* read the data */ + for (y = 0; y < len; y++) { + out[y] = in[x++]; + } + + *outlen = y; + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c b/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c new file mode 100644 index 00000000000..395774c02a2 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_encode_octet_string.c + ASN.1 DER, encode a OCTET STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store an OCTET STRING + @param in The array of OCTETS to store (one per char) + @param inlen The number of OCTETS to store + @param out [out] The destination for the DER encoded OCTET STRING + @param outlen [in/out] The max size and resulting size of the DER OCTET STRING + @return CRYPT_OK if successful +*/ +int der_encode_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); + LTC_ARGCHK(outlen != NULL); + + /* get the size */ + if ((err = der_length_octet_string(inlen, &len)) != CRYPT_OK) { + return err; + } + + /* too big? */ + if (len > *outlen) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + /* 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; + } + + /* store octets */ + for (y = 0; y < inlen; y++) { + out[x++] = in[y]; + } + + /* retun length */ + *outlen = x; + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c b/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c new file mode 100644 index 00000000000..25ff5f8291c --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_length_octet_string.c + ASN.1 DER, get length of OCTET STRING, Tom St Denis +*/ + +#ifdef LTC_DER +/** + Gets length of DER encoding of OCTET STRING + @param noctets The number of octets in the string to encode + @param outlen [out] The length of the DER encoding for the given string + @return CRYPT_OK if successful +*/ +int der_length_octet_string(unsigned long noctets, unsigned long *outlen) +{ + 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; + } + + return CRYPT_OK; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c,v $ */ +/* $Revision: 1.3 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/octet/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/octet/sub.mk new file mode 100644 index 00000000000..04607eed502 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/octet/sub.mk @@ -0,0 +1,3 @@ +srcs-y += der_decode_octet_string.c +srcs-y += der_encode_octet_string.c +srcs-y += der_length_octet_string.c diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c b/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c new file mode 100644 index 00000000000..4688c38dc1f --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_decode_printable_string.c + ASN.1 DER, encode a printable STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store a printable STRING + @param in The DER encoded printable STRING + @param inlen The size of the DER printable STRING + @param out [out] The array of octets stored (one per char) + @param outlen [in/out] The number of octets stored + @return CRYPT_OK if successful +*/ +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; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* must have header at least */ + if (inlen < 2) { + return CRYPT_INVALID_PACKET; + } + + /* check for 0x13 */ + if ((in[0] & 0x1F) != 0x13) { + return CRYPT_INVALID_PACKET; + } + 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; + } + + /* is it too long? */ + if (len > *outlen) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + if (len + x > inlen) { + return CRYPT_INVALID_PACKET; + } + + /* read the data */ + for (y = 0; y < len; y++) { + t = der_printable_value_decode(in[x++]); + if (t == -1) { + return CRYPT_INVALID_ARG; + } + out[y] = t; + } + + *outlen = y; + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c b/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c new file mode 100644 index 00000000000..f94bd5e1475 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_encode_printable_string.c + ASN.1 DER, encode a printable STRING, Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Store an printable STRING + @param in The array of printable to store (one per char) + @param inlen The number of printable to store + @param out [out] The destination for the DER encoded printable STRING + @param outlen [in/out] The max size and resulting size of the DER printable STRING + @return CRYPT_OK if successful +*/ +int der_encode_printable_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); + LTC_ARGCHK(outlen != NULL); + + /* get the size */ + if ((err = der_length_printable_string(in, inlen, &len)) != CRYPT_OK) { + return err; + } + + /* too big? */ + if (len > *outlen) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + /* 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; + } + + /* store octets */ + for (y = 0; y < inlen; y++) { + out[x++] = der_printable_char_encode(in[y]); + } + + /* retun length */ + *outlen = x; + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c b/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c new file mode 100644 index 00000000000..73cd8eec937 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_length_printable_string.c + ASN.1 DER, get length of Printable STRING, Tom St Denis +*/ + +#ifdef LTC_DER + +static const struct { + int code, value; +} printable_table[] = { +{ ' ', 32 }, +{ '\'', 39 }, +{ '(', 40 }, +{ ')', 41 }, +{ '+', 43 }, +{ ',', 44 }, +{ '-', 45 }, +{ '.', 46 }, +{ '/', 47 }, +{ '0', 48 }, +{ '1', 49 }, +{ '2', 50 }, +{ '3', 51 }, +{ '4', 52 }, +{ '5', 53 }, +{ '6', 54 }, +{ '7', 55 }, +{ '8', 56 }, +{ '9', 57 }, +{ ':', 58 }, +{ '=', 61 }, +{ '?', 63 }, +{ 'A', 65 }, +{ 'B', 66 }, +{ 'C', 67 }, +{ 'D', 68 }, +{ 'E', 69 }, +{ 'F', 70 }, +{ 'G', 71 }, +{ 'H', 72 }, +{ 'I', 73 }, +{ 'J', 74 }, +{ 'K', 75 }, +{ 'L', 76 }, +{ 'M', 77 }, +{ 'N', 78 }, +{ 'O', 79 }, +{ 'P', 80 }, +{ 'Q', 81 }, +{ 'R', 82 }, +{ 'S', 83 }, +{ 'T', 84 }, +{ 'U', 85 }, +{ 'V', 86 }, +{ 'W', 87 }, +{ 'X', 88 }, +{ 'Y', 89 }, +{ 'Z', 90 }, +{ 'a', 97 }, +{ 'b', 98 }, +{ 'c', 99 }, +{ 'd', 100 }, +{ 'e', 101 }, +{ 'f', 102 }, +{ 'g', 103 }, +{ 'h', 104 }, +{ 'i', 105 }, +{ 'j', 106 }, +{ 'k', 107 }, +{ 'l', 108 }, +{ 'm', 109 }, +{ 'n', 110 }, +{ 'o', 111 }, +{ 'p', 112 }, +{ 'q', 113 }, +{ 'r', 114 }, +{ 's', 115 }, +{ 't', 116 }, +{ 'u', 117 }, +{ 'v', 118 }, +{ 'w', 119 }, +{ 'x', 120 }, +{ 'y', 121 }, +{ 'z', 122 }, +}; + +int der_printable_char_encode(int c) +{ + int x; + for (x = 0; x < (int)(sizeof(printable_table)/sizeof(printable_table[0])); x++) { + if (printable_table[x].code == c) { + return printable_table[x].value; + } + } + return -1; +} + +int der_printable_value_decode(int v) +{ + int x; + for (x = 0; x < (int)(sizeof(printable_table)/sizeof(printable_table[0])); x++) { + if (printable_table[x].value == v) { + return printable_table[x].code; + } + } + return -1; +} + +/** + Gets length of DER encoding of Printable STRING + @param octets The values you want to encode + @param noctets The number of octets in the string to encode + @param outlen [out] The length of the DER encoding for the given string + @return CRYPT_OK if successful +*/ +int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen) +{ + unsigned long x; + + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(octets != NULL); + + /* scan string for validity */ + for (x = 0; x < noctets; x++) { + if (der_printable_char_encode(octets[x]) == -1) { + return CRYPT_INVALID_ARG; + } + } + + 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; + } + + return CRYPT_OK; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c,v $ */ +/* $Revision: 1.3 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/sub.mk new file mode 100644 index 00000000000..b509209aea3 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/sub.mk @@ -0,0 +1,3 @@ +srcs-y += der_decode_printable_string.c +srcs-y += der_encode_printable_string.c +srcs-y += der_length_printable_string.c diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c new file mode 100644 index 00000000000..dcac6e52658 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" +#include + + +/** + @file der_decode_sequence_ex.c + ASN.1 DER, decode a SEQUENCE, Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Decode a SEQUENCE + @param in The DER encoded input + @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 + @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) +{ + int err, type; + unsigned long size, x, y, z, i, blksize=0; + 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; + + if (in[x] < 128) { + blksize = in[x++]; + } else if (in[x] & 0x80) { + 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 < outlen; i++) { + list[i].used = 0; + } + + /* ok read data */ + inlen = blksize; + for (i = 0; i < 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; + } + + switch (type) { + case LTC_ASN1_BOOLEAN: + z = inlen; + if ((err = der_decode_boolean(in + x, z, ((int *)data))) != CRYPT_OK) { + 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) { 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) { 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) { 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) { 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) { 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) { 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_IA5_STRING: + z = inlen; + if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) { + if (!ordered) { 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) { 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) { 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) { 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) { 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) { 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) { continue; } + goto LBL_ERR; + } + break; + + default: + 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 < outlen; i++) { + if (list[i].used == 0) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + } + err = CRYPT_OK; + +LBL_ERR: + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c,v $ */ +/* $Revision: 1.16 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c new file mode 100644 index 00000000000..621b0956b20 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c @@ -0,0 +1,413 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_decode_sequence_flexi.c + ASN.1 DER, decode an array of ASN.1 types with a flexi parser, Tom St Denis +*/ + +#ifdef LTC_DER + +static unsigned long fetch_length(const unsigned char *in, unsigned long inlen) +{ + unsigned long x, y, z; + + y = 0; + + /* skip type and read len */ + if (inlen < 2) { + return 0xFFFFFFFF; + } + ++in; ++y; + + /* read len */ + x = *in++; ++y; + + /* <128 means literal */ + if (x < 128) { + return x+y; + } + 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; + } + + y += x; + z = 0; + while (x--) { + z = (z<<8) | ((unsigned long)*in); + ++in; + } + return z+y; +} + +/** + ASN.1 DER Flexi(ble) decoder will decode arbitrary DER packets and create a linked list of the decoded elements. + @param in The input buffer + @param inlen [in/out] The length of the input buffer and on output the amount of decoded data + @param out [out] A pointer to the linked list + @return CRYPT_OK on success. +*/ +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, x, y; + void *realloc_tmp; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen != NULL); + LTC_ARGCHK(out != NULL); + + l = NULL; + totlen = 0; + + /* 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); + if (len > *inlen) { + err = CRYPT_INVALID_PACKET; + goto error; + } + + /* alloc new link */ + if (l == NULL) { + l = XCALLOC(1, sizeof(*l)); + if (l == NULL) { + err = CRYPT_MEM; + goto error; + } + } else { + l->next = XCALLOC(1, sizeof(*l)); + if (l->next == NULL) { + err = CRYPT_MEM; + goto error; + } + l->next->prev = l; + l = l->next; + } + + /* now switch on type */ + switch (type) { + case 0x01: /* BOOLEAN */ + l->type = LTC_ASN1_BOOLEAN; + l->size = 1; + l->data = XCALLOC(1, sizeof(int)); + + if ((err = der_decode_boolean(in, *inlen, l->data)) != CRYPT_OK) { + goto error; + } + + if ((err = der_length_boolean(&len)) != CRYPT_OK) { + goto error; + } + break; + + case 0x02: /* INTEGER */ + /* init field */ + l->type = LTC_ASN1_INTEGER; + l->size = 1; + if ((err = mp_init(&l->data)) != CRYPT_OK) { + goto error; + } + + /* decode field */ + if ((err = der_decode_integer(in, *inlen, l->data)) != CRYPT_OK) { + goto error; + } + + /* calc length of object */ + if ((err = der_length_integer(l->data, &len)) != CRYPT_OK) { + goto error; + } + break; + + case 0x03: /* BIT */ + /* 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) { + err = CRYPT_MEM; + goto error; + } + + if ((err = der_decode_bit_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { + goto error; + } + + if ((err = der_length_bit_string(l->size, &len)) != CRYPT_OK) { + goto error; + } + break; + + case 0x04: /* OCTET */ + + /* init field */ + l->type = LTC_ASN1_OCTET_STRING; + l->size = len; + + if ((l->data = XCALLOC(1, l->size)) == NULL) { + err = CRYPT_MEM; + goto error; + } + + if ((err = der_decode_octet_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { + goto error; + } + + if ((err = der_length_octet_string(l->size, &len)) != CRYPT_OK) { + goto error; + } + break; + + case 0x05: /* NULL */ + + /* valid NULL is 0x05 0x00 */ + if (in[0] != 0x05 || in[1] != 0x00) { + err = CRYPT_INVALID_PACKET; + goto error; + } + + /* simple to store ;-) */ + l->type = LTC_ASN1_NULL; + l->data = NULL; + l->size = 0; + len = 2; + + break; + + case 0x06: /* OID */ + + /* init field */ + l->type = LTC_ASN1_OBJECT_IDENTIFIER; + l->size = len; + + if ((l->data = XCALLOC(len, sizeof(unsigned long))) == NULL) { + err = CRYPT_MEM; + goto error; + } + + if ((err = der_decode_object_identifier(in, *inlen, l->data, &l->size)) != CRYPT_OK) { + goto error; + } + + if ((err = der_length_object_identifier(l->data, l->size, &len)) != CRYPT_OK) { + goto error; + } + + /* resize it to save a bunch of mem */ + if ((realloc_tmp = XREALLOC(l->data, l->size * sizeof(unsigned long))) == NULL) { + /* out of heap but this is not an error */ + break; + } + l->data = realloc_tmp; + break; + + case 0x0C: /* UTF8 */ + + /* init field */ + l->type = LTC_ASN1_UTF8_STRING; + l->size = len; + + if ((l->data = XCALLOC(sizeof(wchar_t), l->size)) == NULL) { + err = CRYPT_MEM; + goto error; + } + + if ((err = der_decode_utf8_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { + goto error; + } + + if ((err = der_length_utf8_string(l->data, l->size, &len)) != CRYPT_OK) { + goto error; + } + break; + + case 0x13: /* PRINTABLE */ + + /* init field */ + l->type = LTC_ASN1_PRINTABLE_STRING; + l->size = len; + + if ((l->data = XCALLOC(1, l->size)) == NULL) { + err = CRYPT_MEM; + goto error; + } + + if ((err = der_decode_printable_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { + goto error; + } + + if ((err = der_length_printable_string(l->data, l->size, &len)) != CRYPT_OK) { + goto error; + } + break; + + case 0x16: /* IA5 */ + + /* init field */ + l->type = LTC_ASN1_IA5_STRING; + l->size = len; + + if ((l->data = XCALLOC(1, l->size)) == NULL) { + err = CRYPT_MEM; + goto error; + } + + if ((err = der_decode_ia5_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { + goto error; + } + + if ((err = der_length_ia5_string(l->data, l->size, &len)) != CRYPT_OK) { + goto error; + } + break; + + case 0x17: /* UTC TIME */ + + /* init field */ + l->type = LTC_ASN1_UTCTIME; + l->size = 1; + + if ((l->data = XCALLOC(1, sizeof(ltc_utctime))) == NULL) { + err = CRYPT_MEM; + goto error; + } + + len = *inlen; + if ((err = der_decode_utctime(in, &len, l->data)) != CRYPT_OK) { + goto error; + } + + if ((err = der_length_utctime(l->data, &len)) != CRYPT_OK) { + goto error; + } + break; + + case 0x30: /* SEQUENCE */ + case 0x31: /* SET */ + + /* init field */ + l->type = (type == 0x30) ? LTC_ASN1_SEQUENCE : LTC_ASN1_SET; + + /* we have to decode the SEQUENCE header and get it's length */ + + /* move past type */ + ++in; --(*inlen); + + /* read length byte */ + x = *in++; --(*inlen); + + /* smallest SEQUENCE/SET header */ + y = 2; + + /* now if it's > 127 the next bytes are the length of the length */ + if (x > 128) { + x &= 0x7F; + in += x; + *inlen -= x; + + /* update sequence header len */ + y += x; + } + + /* Sequence elements go as child */ + len = len - y; + if ((err = der_decode_sequence_flexi(in, &len, &(l->child))) != CRYPT_OK) { + goto error; + } + + /* len update */ + totlen += y; + + /* link them up y0 */ + l->child->parent = l; + + break; + default: + /* invalid byte ... this is a soft error */ + /* remove link */ + l = l->prev; + XFREE(l->next); + l->next = NULL; + goto outside; + } + + /* advance pointers */ + totlen += len; + in += len; + *inlen -= len; + } + +outside: + + /* rewind l please */ + while (l->prev != NULL || l->parent != NULL) { + if (l->parent != NULL) { + l = l->parent; + } else { + l = l->prev; + } + } + + /* return */ + *out = l; + *inlen = totlen; + return CRYPT_OK; + +error: + /* free list */ + der_sequence_free(l); + + return err; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c,v $ */ +/* $Revision: 1.26 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c new file mode 100644 index 00000000000..fae6f6a99cd --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" +#include + + +/** + @file der_decode_sequence_multi.c + ASN.1 DER, decode a SEQUENCE, Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Decode a SEQUENCE type using a VA list + @param in Input buffer + @param inlen Length of input in octets + @remark <...> is of the form (int, unsigned long, void*) + @return CRYPT_OK on success +*/ +int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...) +{ + int err, 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 = va_arg(args, int); + size = va_arg(args, unsigned long); + data = va_arg(args, void*); + + if (type == LTC_ASN1_EOL) { + break; + } + + switch (type) { + case LTC_ASN1_BOOLEAN: + case LTC_ASN1_INTEGER: + case LTC_ASN1_SHORT_INTEGER: + case LTC_ASN1_BIT_STRING: + case LTC_ASN1_OCTET_STRING: + case LTC_ASN1_NULL: + case LTC_ASN1_OBJECT_IDENTIFIER: + case LTC_ASN1_IA5_STRING: + case LTC_ASN1_PRINTABLE_STRING: + case LTC_ASN1_UTF8_STRING: + case LTC_ASN1_UTCTIME: + case LTC_ASN1_SET: + case LTC_ASN1_SETOF: + case LTC_ASN1_SEQUENCE: + case LTC_ASN1_CHOICE: + ++x; + break; + + default: + va_end(args); + return CRYPT_INVALID_ARG; + } + } + va_end(args); + + /* allocate structure for x elements */ + if (x == 0) { + return CRYPT_NOP; + } + + list = XCALLOC(sizeof(*list), x); + if (list == NULL) { + return CRYPT_MEM; + } + + /* fill in the structure */ + va_start(args, inlen); + x = 0; + for (;;) { + type = va_arg(args, int); + size = va_arg(args, unsigned long); + data = va_arg(args, void*); + + if (type == LTC_ASN1_EOL) { + break; + } + + switch (type) { + case LTC_ASN1_BOOLEAN: + case LTC_ASN1_INTEGER: + case LTC_ASN1_SHORT_INTEGER: + case LTC_ASN1_BIT_STRING: + case LTC_ASN1_OCTET_STRING: + case LTC_ASN1_NULL: + case LTC_ASN1_OBJECT_IDENTIFIER: + case LTC_ASN1_IA5_STRING: + case LTC_ASN1_PRINTABLE_STRING: + case LTC_ASN1_UTF8_STRING: + case LTC_ASN1_UTCTIME: + case LTC_ASN1_SEQUENCE: + case LTC_ASN1_SET: + case LTC_ASN1_SETOF: + case LTC_ASN1_CHOICE: + list[x].type = type; + list[x].size = size; + list[x++].data = data; + break; + + default: + va_end(args); + err = CRYPT_INVALID_ARG; + goto LBL_ERR; + } + } + va_end(args); + + err = der_decode_sequence(in, inlen, list, x); +LBL_ERR: + XFREE(list); + return err; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c,v $ */ +/* $Revision: 1.13 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c new file mode 100644 index 00000000000..d85feeaa185 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" +#include + + +/** + @file der_encode_sequence_ex.c + ASN.1 DER, encode a SEQUENCE, Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Encode a SEQUENCE + @param list The list of items to encode + @param inlen The number of items in the list + @param out [out] The destination + @param outlen [in/out] The size of the output + @param type_of LTC_ASN1_SEQUENCE or LTC_ASN1_SET/LTC_ASN1_SETOF + @return CRYPT_OK on success +*/ +int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int type_of) +{ + int err, type; + unsigned long size, x, y, z, i; + void *data; + + LTC_ARGCHK(list != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* get size of output that will be required */ + y = 0; + for (i = 0; i < inlen; i++) { + type = list[i].type; + size = list[i].size; + data = list[i].data; + + if (type == LTC_ASN1_EOL) { + break; + } + + 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: + 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_PRINTABLE_STRING: + if ((err = der_length_printable_string(data, size, &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_UTCTIME: + if ((err = der_length_utctime(data, &x)) != 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; + + default: + 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; + goto LBL_ERR; + } + + /* too big ? */ + if (*outlen < y) { + *outlen = y; + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + + /* store header */ + 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); + } + + /* store data */ + *outlen -= x; + for (i = 0; i < inlen; i++) { + 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; + } + x += z; + *outlen -= z; + break; + + case LTC_ASN1_INTEGER: + z = *outlen; + if ((err = der_encode_integer(data, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + *outlen -= z; + 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; + } + x += z; + *outlen -= z; + break; + + case LTC_ASN1_BIT_STRING: + z = *outlen; + if ((err = der_encode_bit_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + *outlen -= z; + break; + + case LTC_ASN1_OCTET_STRING: + z = *outlen; + if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + *outlen -= z; + break; + + case LTC_ASN1_NULL: + out[x++] = 0x05; + out[x++] = 0x00; + *outlen -= 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; + } + x += z; + *outlen -= z; + break; + + case LTC_ASN1_IA5_STRING: + z = *outlen; + if ((err = der_encode_ia5_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + *outlen -= z; + break; + + case LTC_ASN1_PRINTABLE_STRING: + z = *outlen; + if ((err = der_encode_printable_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + *outlen -= z; + break; + + case LTC_ASN1_UTF8_STRING: + z = *outlen; + if ((err = der_encode_utf8_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + *outlen -= z; + break; + + case LTC_ASN1_UTCTIME: + z = *outlen; + if ((err = der_encode_utctime(data, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + *outlen -= z; + break; + + case LTC_ASN1_SET: + z = *outlen; + if ((err = der_encode_set(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + *outlen -= z; + break; + + case LTC_ASN1_SETOF: + z = *outlen; + if ((err = der_encode_setof(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + *outlen -= z; + break; + + case LTC_ASN1_SEQUENCE: + z = *outlen; + if ((err = der_encode_sequence_ex(data, size, out + x, &z, type)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + *outlen -= z; + break; + + default: + err = CRYPT_INVALID_ARG; + goto LBL_ERR; + } + } + *outlen = x; + err = CRYPT_OK; + +LBL_ERR: + return err; +} + +#endif diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c new file mode 100644 index 00000000000..c3e3a1d3415 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" +#include + + +/** + @file der_encode_sequence_multi.c + ASN.1 DER, encode a SEQUENCE, Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Encode a SEQUENCE type using a VA list + @param out [out] Destination for data + @param outlen [in/out] Length of buffer and resulting length of output + @remark <...> is of the form (int, unsigned long, void*) + @return CRYPT_OK on success +*/ +int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) +{ + int err, type; + unsigned long size, x; + void *data; + va_list args; + ltc_asn1_list *list; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* get size of output that will be required */ + va_start(args, outlen); + x = 0; + for (;;) { + type = va_arg(args, int); + size = va_arg(args, unsigned long); + data = va_arg(args, void*); + + if (type == LTC_ASN1_EOL) { + break; + } + + switch (type) { + case LTC_ASN1_BOOLEAN: + case LTC_ASN1_INTEGER: + case LTC_ASN1_SHORT_INTEGER: + case LTC_ASN1_BIT_STRING: + case LTC_ASN1_OCTET_STRING: + case LTC_ASN1_NULL: + case LTC_ASN1_OBJECT_IDENTIFIER: + case LTC_ASN1_IA5_STRING: + case LTC_ASN1_PRINTABLE_STRING: + case LTC_ASN1_UTF8_STRING: + case LTC_ASN1_UTCTIME: + case LTC_ASN1_SEQUENCE: + case LTC_ASN1_SET: + case LTC_ASN1_SETOF: + ++x; + break; + + default: + va_end(args); + return CRYPT_INVALID_ARG; + } + } + va_end(args); + + /* allocate structure for x elements */ + if (x == 0) { + return CRYPT_NOP; + } + + list = XCALLOC(sizeof(*list), x); + if (list == NULL) { + return CRYPT_MEM; + } + + /* fill in the structure */ + va_start(args, outlen); + x = 0; + for (;;) { + type = va_arg(args, int); + size = va_arg(args, unsigned long); + data = va_arg(args, void*); + + if (type == LTC_ASN1_EOL) { + break; + } + + switch (type) { + case LTC_ASN1_BOOLEAN: + case LTC_ASN1_INTEGER: + case LTC_ASN1_SHORT_INTEGER: + case LTC_ASN1_BIT_STRING: + case LTC_ASN1_OCTET_STRING: + case LTC_ASN1_NULL: + case LTC_ASN1_OBJECT_IDENTIFIER: + case LTC_ASN1_IA5_STRING: + case LTC_ASN1_PRINTABLE_STRING: + case LTC_ASN1_UTF8_STRING: + case LTC_ASN1_UTCTIME: + case LTC_ASN1_SEQUENCE: + case LTC_ASN1_SET: + case LTC_ASN1_SETOF: + list[x].type = type; + list[x].size = size; + list[x++].data = data; + break; + + default: + va_end(args); + err = CRYPT_INVALID_ARG; + goto LBL_ERR; + } + } + va_end(args); + + err = der_encode_sequence(list, x, out, outlen); +LBL_ERR: + XFREE(list); + return err; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c,v $ */ +/* $Revision: 1.12 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c new file mode 100644 index 00000000000..eb8526d41a9 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_length_sequence.c + ASN.1 DER, length a SEQUENCE, Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Get the length of a DER sequence + @param list The sequences of items in the SEQUENCE + @param inlen The number of items + @param outlen [out] The length required in octets to store it + @return CRYPT_OK on success +*/ +int der_length_sequence(ltc_asn1_list *list, unsigned long inlen, + unsigned long *outlen) +{ + int err, type; + unsigned long size, x, y, i; + void *data; + + LTC_ARGCHK(list != NULL); + LTC_ARGCHK(outlen != NULL); + + /* get size of output that will be required */ + y = 0; + for (i = 0; i < inlen; i++) { + type = list[i].type; + size = list[i].size; + data = list[i].data; + + if (type == LTC_ASN1_EOL) { + break; + } + + 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: + 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_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_UTF8_STRING: + if ((err = der_length_utf8_string(data, size, &x)) != 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; + + + default: + err = CRYPT_INVALID_ARG; + goto LBL_ERR; + } + } + + /* calc header size */ + 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; + goto LBL_ERR; + } + + /* store size */ + *outlen = y; + err = CRYPT_OK; + +LBL_ERR: + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c,v $ */ +/* $Revision: 1.14 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c new file mode 100644 index 00000000000..29dc29343e5 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_sequence_free.c + ASN.1 DER, free's a structure allocated by der_decode_sequence_flexi(), Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Free memory allocated by der_decode_sequence_flexi() + @param in The list to free +*/ +void der_sequence_free(ltc_asn1_list *in) +{ + ltc_asn1_list *l; + + /* walk to the start of the chain */ + while (in->prev != NULL || in->parent != NULL) { + if (in->parent != NULL) { + in = in->parent; + } else { + in = in->prev; + } + } + + /* now walk the list and free stuff */ + while (in != NULL) { + /* is there a child? */ + if (in->child) { + /* disconnect */ + in->child->parent = NULL; + der_sequence_free(in->child); + } + + switch (in->type) { + case LTC_ASN1_SET: + case LTC_ASN1_SETOF: + case LTC_ASN1_SEQUENCE: break; + case LTC_ASN1_INTEGER : if (in->data != NULL) { mp_clear(in->data); } break; + default : if (in->data != NULL) { XFREE(in->data); } + } + + /* move to next and free current */ + l = in->next; + free(in); + in = l; + } +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/sequence/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/sub.mk new file mode 100644 index 00000000000..d44420b0df8 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/sub.mk @@ -0,0 +1,7 @@ +srcs-y += der_decode_sequence_ex.c +srcs-y += der_decode_sequence_flexi.c +srcs-y += der_decode_sequence_multi.c +srcs-y += der_encode_sequence_ex.c +srcs-y += der_encode_sequence_multi.c +srcs-y += der_length_sequence.c +srcs-y += der_sequence_free.c diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c b/core/lib/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c new file mode 100644 index 00000000000..a22e982d92c --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_encode_set.c + ASN.1 DER, Encode a SET, Tom St Denis +*/ + +#ifdef LTC_DER + +/* LTC define to ASN.1 TAG */ +static int ltc_to_asn1(int v) +{ + switch (v) { + case LTC_ASN1_BOOLEAN: return 0x01; + case LTC_ASN1_INTEGER: + case LTC_ASN1_SHORT_INTEGER: return 0x02; + 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_IA5_STRING: return 0x16; + case LTC_ASN1_UTCTIME: return 0x17; + case LTC_ASN1_SEQUENCE: return 0x30; + case LTC_ASN1_SET: + case LTC_ASN1_SETOF: return 0x31; + default: return -1; + } +} + + +static int qsort_helper(const void *a, const void *b) +{ + ltc_asn1_list *A = (ltc_asn1_list *)a, *B = (ltc_asn1_list *)b; + int r; + + r = ltc_to_asn1(A->type) - ltc_to_asn1(B->type); + + /* for QSORT the order is UNDEFINED if they are "equal" which means it is NOT DETERMINISTIC. So we force it to be :-) */ + if (r == 0) { + /* their order in the original list now determines the position */ + return A->used - B->used; + } else { + return r; + } +} + +/* + Encode a SET type + @param list The list of items to encode + @param inlen The number of items in the list + @param out [out] The destination + @param outlen [in/out] The size of the output + @return CRYPT_OK on success +*/ +int der_encode_set(ltc_asn1_list *list, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + ltc_asn1_list *copy; + unsigned long x; + int err; + + /* make copy of list */ + copy = XCALLOC(inlen, sizeof(*copy)); + if (copy == NULL) { + return CRYPT_MEM; + } + + /* fill in used member with index so we can fully sort it */ + for (x = 0; x < inlen; x++) { + copy[x] = list[x]; + copy[x].used = x; + } + + /* sort it by the "type" field */ + XQSORT(copy, inlen, sizeof(*copy), &qsort_helper); + + /* call der_encode_sequence_ex() */ + err = der_encode_sequence_ex(copy, inlen, out, outlen, LTC_ASN1_SET); + + /* free list */ + XFREE(copy); + + return err; +} + + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c,v $ */ +/* $Revision: 1.12 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c b/core/lib/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c new file mode 100644 index 00000000000..822bc8c3bf2 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_encode_setof.c + ASN.1 DER, Encode SET OF, Tom St Denis +*/ + +#ifdef LTC_DER + +struct edge { + unsigned char *start; + unsigned long size; +}; + +static int qsort_helper(const void *a, const void *b) +{ + struct edge *A = (struct edge *)a, *B = (struct edge *)b; + int r; + unsigned long x; + + /* compare min length */ + r = XMEMCMP(A->start, B->start, MIN(A->size, B->size)); + + if (r == 0 && A->size != B->size) { + if (A->size > B->size) { + for (x = B->size; x < A->size; x++) { + if (A->start[x]) { + return 1; + } + } + } else { + for (x = A->size; x < B->size; x++) { + if (B->start[x]) { + return -1; + } + } + } + } + + return r; +} + +/** + Encode a SETOF stucture + @param list The list of items to encode + @param inlen The number of items in the list + @param out [out] The destination + @param outlen [in/out] The size of the output + @return CRYPT_OK on success +*/ +int der_encode_setof(ltc_asn1_list *list, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y, z, hdrlen; + int err; + struct edge *edges; + unsigned char *ptr, *buf; + + /* check that they're all the same type */ + for (x = 1; x < inlen; x++) { + if (list[x].type != list[x-1].type) { + return CRYPT_INVALID_ARG; + } + } + + /* alloc buffer to store copy of output */ + buf = XCALLOC(1, *outlen); + if (buf == NULL) { + return CRYPT_MEM; + } + + /* encode list */ + if ((err = der_encode_sequence_ex(list, inlen, buf, outlen, LTC_ASN1_SETOF)) != CRYPT_OK) { + XFREE(buf); + return err; + } + + /* allocate edges */ + edges = XCALLOC(inlen, sizeof(*edges)); + if (edges == NULL) { + XFREE(buf); + return CRYPT_MEM; + } + + /* skip header */ + ptr = buf + 1; + + /* now skip length data */ + x = *ptr++; + if (x >= 0x80) { + ptr += (x & 0x7F); + } + + /* get the size of the static header */ + hdrlen = ((unsigned long)ptr) - ((unsigned long)buf); + + + /* scan for edges */ + x = 0; + while (ptr < (buf + *outlen)) { + /* store start */ + edges[x].start = ptr; + + /* skip type */ + z = 1; + + /* parse length */ + y = ptr[z++]; + if (y < 128) { + edges[x].size = y; + } else { + y &= 0x7F; + edges[x].size = 0; + while (y--) { + edges[x].size = (edges[x].size << 8) | ((unsigned long)ptr[z++]); + } + } + + /* skip content */ + edges[x].size += z; + ptr += edges[x].size; + ++x; + } + + /* sort based on contents (using edges) */ + XQSORT(edges, inlen, sizeof(*edges), &qsort_helper); + + /* copy static header */ + XMEMCPY(out, buf, hdrlen); + + /* copy+sort using edges+indecies to output from buffer */ + for (y = hdrlen, x = 0; x < inlen; x++) { + XMEMCPY(out+y, edges[x].start, edges[x].size); + y += edges[x].size; + } + +#ifdef LTC_CLEAN_STACK + zeromem(buf, *outlen); +#endif + + /* free buffers */ + XFREE(edges); + XFREE(buf); + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c,v $ */ +/* $Revision: 1.12 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/set/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/set/sub.mk new file mode 100644 index 00000000000..52525d60769 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/set/sub.mk @@ -0,0 +1,2 @@ +srcs-y += der_encode_set.c +srcs-y += der_encode_setof.c diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c b/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c new file mode 100644 index 00000000000..462f750363f --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_decode_short_integer.c + ASN.1 DER, decode an integer, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Read a short integer + @param in The DER encoded data + @param inlen Size of data + @param num [out] The integer to decode + @return CRYPT_OK if successful +*/ +int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsigned long *num) +{ + unsigned long len, x, y; + + LTC_ARGCHK(num != NULL); + LTC_ARGCHK(in != NULL); + + /* check length */ + if (inlen < 2) { + return CRYPT_INVALID_PACKET; + } + + /* check header */ + x = 0; + if ((in[x++] & 0x1F) != 0x02) { + return CRYPT_INVALID_PACKET; + } + + /* get the packet len */ + len = in[x++]; + + if (x + len > inlen) { + return CRYPT_INVALID_PACKET; + } + + /* read number */ + y = 0; + while (len--) { + y = (y<<8) | (unsigned long)in[x++]; + } + *num = y; + + return CRYPT_OK; + +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c b/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c new file mode 100644 index 00000000000..2f2cf33f574 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_encode_short_integer.c + ASN.1 DER, encode an integer, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store a short integer in the range (0,2^32-1) + @param num The integer to encode + @param out [out] The destination for the DER encoded integers + @param outlen [in/out] The max size and resulting size of the DER encoded integers + @return CRYPT_OK if successful +*/ +int der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen) +{ + unsigned long len, x, y, z; + int err; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* force to 32 bits */ + num &= 0xFFFFFFFFUL; + + /* find out how big this will be */ + if ((err = der_length_short_integer(num, &len)) != CRYPT_OK) { + return err; + } + + if (*outlen < len) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + /* get len of output */ + z = 0; + y = num; + while (y) { + ++z; + y >>= 8; + } + + /* handle zero */ + if (z == 0) { + z = 1; + } + + /* see if msb is set */ + z += (num&(1UL<<((z<<3) - 1))) ? 1 : 0; + + /* adjust the number so the msB is non-zero */ + for (x = 0; (z <= 4) && (x < (4 - z)); x++) { + num <<= 8; + } + + /* store header */ + x = 0; + out[x++] = 0x02; + out[x++] = (unsigned char)z; + + /* if 31st bit is set output a leading zero and decrement count */ + if (z == 5) { + out[x++] = 0; + --z; + } + + /* store values */ + for (y = 0; y < z; y++) { + out[x++] = (unsigned char)((num >> 24) & 0xFF); + num <<= 8; + } + + /* we good */ + *outlen = x; + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c b/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c new file mode 100644 index 00000000000..16726978665 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_length_short_integer.c + ASN.1 DER, get length of encoding, Tom St Denis +*/ + + +#ifdef LTC_DER +/** + Gets length of DER encoding of num + @param num The integer to get the size of + @param outlen [out] The length of the DER encoding for the given integer + @return CRYPT_OK if successful +*/ +int der_length_short_integer(unsigned long num, unsigned long *outlen) +{ + unsigned long z, y, len; + + LTC_ARGCHK(outlen != NULL); + + /* force to 32 bits */ + num &= 0xFFFFFFFFUL; + + /* get the number of bytes */ + z = 0; + y = num; + while (y) { + ++z; + y >>= 8; + } + + /* handle zero */ + if (z == 0) { + z = 1; + } + + /* 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; + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/sub.mk new file mode 100644 index 00000000000..fae1f08d1ad --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/sub.mk @@ -0,0 +1,3 @@ +srcs-y += der_decode_short_integer.c +srcs-y += der_encode_short_integer.c +srcs-y += der_length_short_integer.c diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/sub.mk new file mode 100644 index 00000000000..161b5c9f8a5 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/sub.mk @@ -0,0 +1,13 @@ +subdirs-y += bit +subdirs-y += boolean +subdirs-y += choice +subdirs-y += ia5 +subdirs-y += integer +subdirs-y += object_identifier +subdirs-y += octet +subdirs-y += printable_string +subdirs-y += sequence +subdirs-y += set +subdirs-y += short_integer +subdirs-y += utctime +subdirs-y += utf8 diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c b/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c new file mode 100644 index 00000000000..328051d1e20 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_decode_utctime.c + ASN.1 DER, decode a UTCTIME, Tom St Denis +*/ + +#ifdef LTC_DER + +static int char_to_int(unsigned char x) +{ + switch (x) { + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + default: + return 100; + } + return 100; +} + +#define DECODE_V(y, max) \ + y = char_to_int(buf[x])*10 + char_to_int(buf[x+1]); \ + if (y >= max) return CRYPT_INVALID_PACKET; \ + x += 2; + +/** + Decodes a UTC time structure in DER format (reads all 6 valid encoding formats) + @param in Input buffer + @param inlen Length of input buffer in octets + @param out [out] Destination of UTC time structure + @return CRYPT_OK if successful +*/ +int der_decode_utctime(const unsigned char *in, unsigned long *inlen, + ltc_utctime *out) +{ + unsigned char buf[32]; + unsigned long x; + int y; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen != NULL); + LTC_ARGCHK(out != NULL); + + /* check header */ + if (*inlen < 2UL || (in[1] >= sizeof(buf)) || ((in[1] + 2UL) > *inlen)) { + return CRYPT_INVALID_PACKET; + } + + /* decode the string */ + for (x = 0; x < in[1]; x++) { + y = der_ia5_value_decode(in[x+2]); + if (y == -1) { + return CRYPT_INVALID_PACKET; + } + buf[x] = y; + } + *inlen = 2 + x; + + + /* possible encodings are +YYMMDDhhmmZ +YYMMDDhhmm+hh'mm' +YYMMDDhhmm-hh'mm' +YYMMDDhhmmssZ +YYMMDDhhmmss+hh'mm' +YYMMDDhhmmss-hh'mm' + + So let's do a trivial decode upto [including] mm + */ + + x = 0; + DECODE_V(out->YY, 100); + DECODE_V(out->MM, 13); + DECODE_V(out->DD, 32); + DECODE_V(out->hh, 24); + DECODE_V(out->mm, 60); + + /* clear timezone and seconds info */ + out->off_dir = out->off_hh = out->off_mm = out->ss = 0; + + /* now is it Z, +, - or 0-9 */ + if (buf[x] == 'Z') { + return CRYPT_OK; + } else if (buf[x] == '+' || buf[x] == '-') { + out->off_dir = (buf[x++] == '+') ? 0 : 1; + DECODE_V(out->off_hh, 24); + DECODE_V(out->off_mm, 60); + return CRYPT_OK; + } + + /* decode seconds */ + DECODE_V(out->ss, 60); + + /* now is it Z, +, - */ + if (buf[x] == 'Z') { + return CRYPT_OK; + } else if (buf[x] == '+' || buf[x] == '-') { + out->off_dir = (buf[x++] == '+') ? 0 : 1; + DECODE_V(out->off_hh, 24); + DECODE_V(out->off_mm, 60); + return CRYPT_OK; + } else { + return CRYPT_INVALID_PACKET; + } +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c,v $ */ +/* $Revision: 1.9 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c b/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c new file mode 100644 index 00000000000..e22b294a088 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_encode_utctime.c + ASN.1 DER, encode a UTCTIME, Tom St Denis +*/ + +#ifdef LTC_DER + +static const char *baseten = "0123456789"; + +#define STORE_V(y) \ + out[x++] = der_ia5_char_encode(baseten[(y/10) % 10]); \ + out[x++] = der_ia5_char_encode(baseten[y % 10]); + +/** + Encodes a UTC time structure in DER format + @param utctime The UTC time structure to encode + @param out The destination of the DER encoding of the UTC time structure + @param outlen [in/out] The length of the DER encoding + @return CRYPT_OK if successful +*/ +int der_encode_utctime(ltc_utctime *utctime, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, tmplen; + int err; + + LTC_ARGCHK(utctime != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((err = der_length_utctime(utctime, &tmplen)) != CRYPT_OK) { + return err; + } + if (tmplen > *outlen) { + *outlen = tmplen; + return CRYPT_BUFFER_OVERFLOW; + } + + /* store header */ + out[0] = 0x17; + + /* store values */ + x = 2; + STORE_V(utctime->YY); + STORE_V(utctime->MM); + STORE_V(utctime->DD); + STORE_V(utctime->hh); + STORE_V(utctime->mm); + STORE_V(utctime->ss); + + if (utctime->off_mm || utctime->off_hh) { + out[x++] = der_ia5_char_encode(utctime->off_dir ? '-' : '+'); + STORE_V(utctime->off_hh); + STORE_V(utctime->off_mm); + } else { + out[x++] = der_ia5_char_encode('Z'); + } + + /* store length */ + out[1] = (unsigned char)(x - 2); + + /* all good let's return */ + *outlen = x; + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c,v $ */ +/* $Revision: 1.10 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c b/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c new file mode 100644 index 00000000000..055b726a7c6 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_length_utctime.c + ASN.1 DER, get length of UTCTIME, Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Gets length of DER encoding of UTCTIME + @param utctime The UTC time structure to get the size of + @param outlen [out] The length of the DER encoding + @return CRYPT_OK if successful +*/ +int der_length_utctime(ltc_utctime *utctime, unsigned long *outlen) +{ + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(utctime != NULL); + + if (utctime->off_hh == 0 && utctime->off_mm == 0) { + /* we encode as YYMMDDhhmmssZ */ + *outlen = 2 + 13; + } else { + /* we encode as YYMMDDhhmmss{+|-}hh'mm' */ + *outlen = 2 + 17; + } + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/utctime/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/utctime/sub.mk new file mode 100644 index 00000000000..afb3e1bacb3 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/utctime/sub.mk @@ -0,0 +1,3 @@ +srcs-y += der_decode_utctime.c +srcs-y += der_encode_utctime.c +srcs-y += der_length_utctime.c diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c b/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c new file mode 100644 index 00000000000..6226dd51831 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_decode_utf8_string.c + ASN.1 DER, encode a UTF8 STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store a UTF8 STRING + @param in The DER encoded UTF8 STRING + @param inlen The size of the DER UTF8 STRING + @param out [out] The array of utf8s stored (one per char) + @param outlen [in/out] The number of utf8s stored + @return CRYPT_OK if successful +*/ +int der_decode_utf8_string(const unsigned char *in, unsigned long inlen, + wchar_t *out, unsigned long *outlen) +{ + wchar_t tmp; + unsigned long x, y, z, len; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* must have header at least */ + if (inlen < 2) { + return CRYPT_INVALID_PACKET; + } + + /* check for 0x0C */ + if ((in[0] & 0x1F) != 0x0C) { + return CRYPT_INVALID_PACKET; + } + 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; + } + + if (len + x > inlen) { + return CRYPT_INVALID_PACKET; + } + + /* proceed to decode */ + for (y = 0; x < inlen; ) { + /* get first byte */ + tmp = in[x++]; + + /* count number of bytes */ + for (z = 0; (tmp & 0x80) && (z <= 4); z++, tmp = (tmp << 1) & 0xFF); + + if (z > 4 || (x + (z - 1) > inlen)) { + return CRYPT_INVALID_PACKET; + } + + /* decode, grab upper bits */ + tmp >>= z; + + /* grab remaining bytes */ + if (z > 1) { --z; } + while (z-- != 0) { + if ((in[x] & 0xC0) != 0x80) { + return CRYPT_INVALID_PACKET; + } + tmp = (tmp << 6) | ((wchar_t)in[x++] & 0x3F); + } + + if (y > *outlen) { + *outlen = y; + return CRYPT_BUFFER_OVERFLOW; + } + out[y++] = tmp; + } + *outlen = y; + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c b/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c new file mode 100644 index 00000000000..40ff4445a01 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_encode_utf8_string.c + ASN.1 DER, encode a UTF8 STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store an UTF8 STRING + @param in The array of UTF8 to store (one per wchar_t) + @param inlen The number of UTF8 to store + @param out [out] The destination for the DER encoded UTF8 STRING + @param outlen [in/out] The max size and resulting size of the DER UTF8 STRING + @return CRYPT_OK if successful +*/ +int der_encode_utf8_string(const wchar_t *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y, len; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* get the size */ + for (x = len = 0; x < inlen; x++) { + if (in[x] < 0 || in[x] > 0x1FFFF) { + 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; + } + + /* too big? */ + if (y > *outlen) { + *outlen = len; + 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 { + return CRYPT_INVALID_ARG; + } + + /* store UTF8 */ + for (y = 0; y < inlen; y++) { + switch (der_utf8_charsize(in[y])) { + case 1: out[x++] = (unsigned char)in[y]; break; + case 2: out[x++] = 0xC0 | ((in[y] >> 6) & 0x1F); out[x++] = 0x80 | (in[y] & 0x3F); break; + case 3: out[x++] = 0xE0 | ((in[y] >> 12) & 0x0F); out[x++] = 0x80 | ((in[y] >> 6) & 0x3F); out[x++] = 0x80 | (in[y] & 0x3F); break; + case 4: out[x++] = 0xF0 | ((in[y] >> 18) & 0x07); out[x++] = 0x80 | ((in[y] >> 12) & 0x3F); out[x++] = 0x80 | ((in[y] >> 6) & 0x3F); out[x++] = 0x80 | (in[y] & 0x3F); break; + default: break; + } + } + + /* retun length */ + *outlen = x; + + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c,v $ */ +/* $Revision: 1.9 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c b/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c new file mode 100644 index 00000000000..17dd672ecf2 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_length_utf8_string.c + ASN.1 DER, get length of UTF8 STRING, Tom St Denis +*/ + +#ifdef LTC_DER + +/** Return the size in bytes of a UTF-8 character + @param c The UTF-8 character to measure + @return The size in bytes +*/ +unsigned long der_utf8_charsize(const wchar_t c) +{ + if (c <= 0x7F) { + return 1; + } else if (c <= 0x7FF) { + return 2; + } else if (c <= 0xFFFF) { + return 3; + } else { + return 4; + } +} + +/** + Gets length of DER encoding of UTF8 STRING + @param in The characters to measure the length of + @param noctets The number of octets in the string to encode + @param outlen [out] The length of the DER encoding for the given string + @return CRYPT_OK if successful +*/ +int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen) +{ + unsigned long x, len; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(outlen != NULL); + + len = 0; + for (x = 0; x < noctets; x++) { + if (in[x] < 0 || in[x] > 0x10FFFF) { + return CRYPT_INVALID_ARG; + } + 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; + } + + return CRYPT_OK; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/utf8/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/utf8/sub.mk new file mode 100644 index 00000000000..353892996c3 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/der/utf8/sub.mk @@ -0,0 +1,4 @@ +cflags-remove-y += -Wextra +srcs-y += der_decode_utf8_string.c +srcs-y += der_encode_utf8_string.c +srcs-y += der_length_utf8_string.c diff --git a/core/lib/libtomcrypt/src/pk/asn1/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/sub.mk new file mode 100644 index 00000000000..c93e1f18dc5 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/asn1/sub.mk @@ -0,0 +1 @@ +subdirs-y += der diff --git a/core/lib/libtomcrypt/src/pk/dh/dh.c b/core/lib/libtomcrypt/src/pk/dh/dh.c new file mode 100644 index 00000000000..47394f50528 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/dh/dh.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#ifdef LTC_LINARO_FIX_DH + +#include +/* + * Make a DH key [private key pair] + * @param prng An active PRNG state + * @param wprng The index for the PRNG you desire to use + * @param keysize The key size (octets) desired of the private key + * @param q If not null, then the private key is in the range + * [2, q-2] where q is called the subprime + * @param xbits If not 0, then the private key has 'xbits' bits + * @note The private key must always be less than p-1 + * @param key [in/out] Where the newly created DH key will be stored + * g and p are provided as input in the key + * type, x and y are output of this function + * @return CRYPT_OK if successful, note: on error all allocated memory will be + * freed automatically. +*/ + +int dh_make_key(prng_state *prng, int wprng, void *q, int xbits, dh_key *key) +{ + const int limit = 500; /* number of tries */ + int err, i; + int key_size = 0; /* max key size, in bytes */ + int key_size_p = 0; /* key size of p */ + int key_size_q = 0; /* key size of p */ + int key_size_x; /* key size of the random candidate */ + void *arg_mod; + uint8_t *buf = 0; /* intermediate buffer to have a raw random */ + int found = 0; + + /* + * Check the arguments + */ + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(key->g != NULL); + LTC_ARGCHK(key->p != NULL); + err = prng_is_valid(wprng); + if (err != CRYPT_OK) + return err; + + /* + * Set the key size and check constraints + */ + if (xbits) { + LTC_ARGCHK((xbits % 8) == 0); + key_size = xbits / 8; + } + key_size_p = mp_unsigned_bin_size(key->p); + if (q) + key_size_q = mp_unsigned_bin_size(q); + if (key_size) { + /* check the constraints */ + LTC_ARGCHK(key_size <= key_size_p); + LTC_ARGCHK((q == NULL) || (key_size <= key_size_q)); + } else { + if (q) + key_size = MIN(key_size_p, key_size_q); + else + key_size =key_size_p; + } + + /* Set the argument we will make the modulo against to */ + if ((q != NULL) && (key_size_q < key_size_p)) + arg_mod = q; + else + arg_mod = key->p; + + /* initialize the key */ + key->x = NULL; + key->y = NULL; + err = mp_init_multi(&key->x, &key->y, NULL); + if (err != CRYPT_OK) + goto error; + + /* Initialize the buffer used to store the random number */ + buf = XMALLOC(key_size); + if (buf == NULL) { + err = CRYPT_MEM; + goto error; + } + + for (i = 0; (i < limit) && (!found); i++) { + /* generate the private key in a raw-buffer */ + if (prng_descriptor[wprng].read(buf, key_size, prng) != + (unsigned long)key_size) { + err = CRYPT_ERROR_READPRNG; + goto error; + } + + /* make sure it is on the right number of bits */ + if (xbits) + buf[0] |= 0x80; + + /* transform it as a Big Number */ + err = mp_read_unsigned_bin(key->x, buf, key_size); + if (err != CRYPT_OK) + goto error; + + /* + * Transform it as a Big Number compatible with p and q + */ + err = mp_read_unsigned_bin(key->y, buf, key_size); + if (err != CRYPT_OK) + goto error; + err = mp_mod(key->y, arg_mod, key->x); + if (err != CRYPT_OK) + goto error; + + /* + * Check the constraints + * - x < p is ok by construction + * - x < q-1: + * - x contains xbits + */ + if (xbits) { + if (mp_count_bits(key->x) != xbits) + continue; + } + + /* we found a suitable private key key->x */ + found = 1; + } + + if (!found) { + /* key is not found */ + return CRYPT_PK_NOT_FOUND; + } + + /* generate the public key key->y */ + err = mp_exptmod(key->g, key->x, key->p, key->y); + if (err != CRYPT_OK) + goto error; + + /* no error */ + err = CRYPT_OK; + +error: + if (err != CRYPT_OK) + mp_clear_multi(key->x, key->y, NULL); + if (buf) + XFREE(buf); + + return err; +} + +/* + * Free the allocated ram for a DH key + * @param key The key which you wish to free + */ +void dh_free(dh_key *key) +{ + /* + * g and p are not cleared on purpose as they are provided when + * generating the key + */ + if (key->x) { + mp_clear(key->x); + key->x = NULL; + } + if (key->y) { + mp_clear(key->y); + key->y = NULL; + } +} + +/* + * Create a DH shared secret. + * @param private_key The private DH key in the pair + * @param public_key The public DH key in the pair, as a big number + * @param secret The secret (as a big number) + * @return CRYPT_OK if successful + */ +int dh_shared_secret(dh_key *private_key, void *public_key, void *secret) +{ + LTC_ARGCHK(private_key != NULL); + LTC_ARGCHK(public_key != NULL); + LTC_ARGCHK(secret != NULL); + + /* types valid? */ + if (private_key->type != PK_PRIVATE) + return CRYPT_PK_NOT_PRIVATE; + + return mp_exptmod(public_key, private_key->x, private_key->p, secret); +} + +#endif diff --git a/core/lib/libtomcrypt/src/pk/dh/sub.mk b/core/lib/libtomcrypt/src/pk/dh/sub.mk new file mode 100644 index 00000000000..7c36ef15df0 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/dh/sub.mk @@ -0,0 +1,2 @@ +srcs-y += dh.c +cflags-dh.c-y += -Wno-unused-variable diff --git a/core/lib/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c b/core/lib/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c new file mode 100644 index 00000000000..fde55da77db --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file dsa_decrypt_key.c + DSA Crypto, Tom St Denis +*/ + +#ifdef LTC_MDSA + +/** + Decrypt an DSA encrypted key + @param in The ciphertext + @param inlen The length of the ciphertext (octets) + @param out [out] The plaintext + @param outlen [in/out] The max size and resulting size of the plaintext + @param key The corresponding private DSA key + @return CRYPT_OK if successful +*/ +int dsa_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + dsa_key *key) +{ + unsigned char *skey, *expt; + void *g_pub; + unsigned long x, y, hashOID[32]; + int hash, err; + ltc_asn1_list decode[3]; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + /* right key type? */ + if (key->type != PK_PRIVATE) { + return CRYPT_PK_NOT_PRIVATE; + } + + /* decode to find out hash */ + LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, sizeof(hashOID)/sizeof(hashOID[0])); + + if ((err = der_decode_sequence(in, inlen, decode, 1)) != CRYPT_OK) { + return err; + } + + hash = find_hash_oid(hashOID, decode[0].size); + if (hash_is_valid(hash) != CRYPT_OK) { + return CRYPT_INVALID_PACKET; + } + + /* we now have the hash! */ + + if ((err = mp_init(&g_pub)) != CRYPT_OK) { + return err; + } + + /* allocate memory */ + expt = XMALLOC(mp_unsigned_bin_size(key->p) + 1); + skey = XMALLOC(MAXBLOCKSIZE); + if (expt == NULL || skey == NULL) { + if (expt != NULL) { + XFREE(expt); + } + if (skey != NULL) { + XFREE(skey); + } + mp_clear(g_pub); + return CRYPT_MEM; + } + + LTC_SET_ASN1(decode, 1, LTC_ASN1_INTEGER, g_pub, 1UL); + LTC_SET_ASN1(decode, 2, LTC_ASN1_OCTET_STRING, skey, MAXBLOCKSIZE); + + /* read the structure in now */ + if ((err = der_decode_sequence(in, inlen, decode, 3)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* make shared key */ + x = mp_unsigned_bin_size(key->p) + 1; + if ((err = dsa_shared_secret(key->x, g_pub, key, expt, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + + y = MIN(mp_unsigned_bin_size(key->p) + 1, MAXBLOCKSIZE); + if ((err = hash_memory(hash, expt, x, expt, &y)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* ensure the hash of the shared secret is at least as big as the encrypt itself */ + if (decode[2].size > y) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + /* avoid buffer overflow */ + if (*outlen < decode[2].size) { + *outlen = decode[2].size; + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + + /* Decrypt the key */ + for (x = 0; x < decode[2].size; x++) { + out[x] = expt[x] ^ skey[x]; + } + *outlen = x; + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(expt, mp_unsigned_bin_size(key->p) + 1); + zeromem(skey, MAXBLOCKSIZE); +#endif + + XFREE(expt); + XFREE(skey); + + mp_clear(g_pub); + + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c,v $ */ +/* $Revision: 1.11 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c b/core/lib/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c new file mode 100644 index 00000000000..bcf43d928b9 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file dsa_encrypt_key.c + DSA Crypto, Tom St Denis +*/ + +#ifdef LTC_MDSA + +/** + Encrypt a symmetric key with DSA + @param in The symmetric key you want to encrypt + @param inlen The length of the key to encrypt (octets) + @param out [out] The destination for the ciphertext + @param outlen [in/out] The max size and resulting size of the ciphertext + @param prng An active PRNG state + @param wprng The index of the PRNG you wish to use + @param hash The index of the hash you want to use + @param key The DSA key you want to encrypt to + @return CRYPT_OK if successful +*/ +int dsa_encrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, int hash, + dsa_key *key) +{ + unsigned char *expt, *skey; + void *g_pub, *g_priv; + unsigned long x, y; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + /* check that wprng/cipher/hash are not invalid */ + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + if (inlen > hash_descriptor[hash].hashsize) { + return CRYPT_INVALID_HASH; + } + + /* make a random key and export the public copy */ + if ((err = mp_init_multi(&g_pub, &g_priv, NULL)) != CRYPT_OK) { + return err; + } + + expt = XMALLOC(mp_unsigned_bin_size(key->p) + 1); + skey = XMALLOC(MAXBLOCKSIZE); + if (expt == NULL || skey == NULL) { + if (expt != NULL) { + XFREE(expt); + } + if (skey != NULL) { + XFREE(skey); + } + mp_clear_multi(g_pub, g_priv, NULL); + return CRYPT_MEM; + } + + /* make a random x, g^x pair */ + x = mp_unsigned_bin_size(key->q); + if (prng_descriptor[wprng].read(expt, x, prng) != x) { + err = CRYPT_ERROR_READPRNG; + goto LBL_ERR; + } + + /* load x */ + if ((err = mp_read_unsigned_bin(g_priv, expt, x)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* compute y */ + if ((err = mp_exptmod(key->g, g_priv, key->p, g_pub)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* make random key */ + x = mp_unsigned_bin_size(key->p) + 1; + if ((err = dsa_shared_secret(g_priv, key->y, key, expt, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + + y = MAXBLOCKSIZE; + if ((err = hash_memory(hash, expt, x, skey, &y)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* Encrypt key */ + for (x = 0; x < inlen; x++) { + skey[x] ^= in[x]; + } + + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash].OIDlen, hash_descriptor[hash].OID, + LTC_ASN1_INTEGER, 1UL, g_pub, + LTC_ASN1_OCTET_STRING, inlen, skey, + LTC_ASN1_EOL, 0UL, NULL); + +LBL_ERR: +#ifdef LTC_CLEAN_STACK + /* clean up */ + zeromem(expt, mp_unsigned_bin_size(key->p) + 1); + zeromem(skey, MAXBLOCKSIZE); +#endif + + XFREE(skey); + XFREE(expt); + + mp_clear_multi(g_pub, g_priv, NULL); + return err; +} + +#endif +/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c,v $ */ +/* $Revision: 1.9 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/dsa/dsa_export.c b/core/lib/libtomcrypt/src/pk/dsa/dsa_export.c new file mode 100644 index 00000000000..bcece9599e9 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/dsa/dsa_export.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file dsa_export.c + DSA implementation, export key, Tom St Denis +*/ + +#ifdef LTC_MDSA + +/** + Export a DSA key to a binary packet + @param out [out] Where to store the packet + @param outlen [in/out] The max size and resulting size of the packet + @param type The type of key to export (PK_PRIVATE or PK_PUBLIC) + @param key The key to export + @return CRYPT_OK if successful +*/ +int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key) +{ + unsigned char flags[1]; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + /* can we store the static header? */ + if (type == PK_PRIVATE && key->type != PK_PRIVATE) { + return CRYPT_PK_TYPE_MISMATCH; + } + + if (type != PK_PUBLIC && type != PK_PRIVATE) { + return CRYPT_INVALID_ARG; + } + + flags[0] = (type != PK_PUBLIC) ? 1 : 0; + + if (type == PK_PRIVATE) { + return der_encode_sequence_multi(out, outlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_INTEGER, 1UL, key->x, + LTC_ASN1_EOL, 0UL, NULL); + } else { + return der_encode_sequence_multi(out, outlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_EOL, 0UL, NULL); + } +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_export.c,v $ */ +/* $Revision: 1.10 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/dsa/dsa_free.c b/core/lib/libtomcrypt/src/pk/dsa/dsa_free.c new file mode 100644 index 00000000000..ca5b887686c --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/dsa/dsa_free.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file dsa_free.c + DSA implementation, free a DSA key, Tom St Denis +*/ + +#ifdef LTC_MDSA + +/** + Free a DSA key + @param key The key to free from memory +*/ +void dsa_free(dsa_key *key) +{ + LTC_ARGCHKVD(key != NULL); + mp_clear_multi(key->g, key->q, key->p, key->x, key->y, NULL); +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_free.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/dsa/dsa_import.c b/core/lib/libtomcrypt/src/pk/dsa/dsa_import.c new file mode 100644 index 00000000000..322245ee55a --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/dsa/dsa_import.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file dsa_import.c + DSA implementation, import a DSA key, Tom St Denis +*/ + +#ifdef LTC_MDSA + +/** + Import a DSA key + @param in The binary packet to import from + @param inlen The length of the binary packet + @param key [out] Where to store the imported key + @return CRYPT_OK if successful, upon error this function will free all allocated memory +*/ +int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key) +{ + unsigned char flags[1]; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* init key */ + if (mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL) != CRYPT_OK) { + return CRYPT_MEM; + } + + /* get key type */ + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto error; + } + + if (flags[0] == 1) { + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_INTEGER, 1UL, key->x, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto error; + } + key->type = PK_PRIVATE; + } else { + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto error; + } + key->type = PK_PUBLIC; + } + key->qord = mp_unsigned_bin_size(key->q); + + if (key->qord >= LTC_MDSA_MAX_GROUP || key->qord <= 15 || + (unsigned long)key->qord >= mp_unsigned_bin_size(key->p) || (mp_unsigned_bin_size(key->p) - key->qord) >= LTC_MDSA_DELTA) { + err = CRYPT_INVALID_PACKET; + goto error; + } + + return CRYPT_OK; +error: + mp_clear_multi(key->p, key->g, key->q, key->x, key->y, NULL); + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_import.c,v $ */ +/* $Revision: 1.14 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/dsa/dsa_make_key.c b/core/lib/libtomcrypt/src/pk/dsa/dsa_make_key.c new file mode 100644 index 00000000000..32b25e2e8da --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/dsa/dsa_make_key.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file dsa_make_key.c + DSA implementation, generate a DSA key, Tom St Denis +*/ + +#ifdef LTC_MDSA + +/** + Create a DSA key + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param group_size Size of the multiplicative group (octets) + @param modulus_size Size of the modulus (octets) + @param key [out] Where to store the created key + @return CRYPT_OK if successful, upon error this function will free all allocated memory +*/ +int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key) +{ + void *tmp, *tmp2; + int err, res; + unsigned char *buf; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* check prng */ + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + /* check size */ + if (group_size >= LTC_MDSA_MAX_GROUP || group_size <= 15 || + group_size >= modulus_size || (modulus_size - group_size) >= LTC_MDSA_DELTA) { + return CRYPT_INVALID_ARG; + } + + /* allocate ram */ + buf = XMALLOC(LTC_MDSA_DELTA); + if (buf == NULL) { + return CRYPT_MEM; + } + + /* init mp_ints */ + if ((err = mp_init_multi(&tmp, &tmp2, &key->g, &key->q, &key->p, &key->x, &key->y, NULL)) != CRYPT_OK) { + XFREE(buf); + return err; + } + + /* make our prime q */ + if ((err = rand_prime(key->q, group_size, prng, wprng)) != CRYPT_OK) { goto error; } + + /* double q */ + if ((err = mp_add(key->q, key->q, tmp)) != CRYPT_OK) { goto error; } + + /* now make a random string and multply it against q */ + if (prng_descriptor[wprng].read(buf+1, modulus_size - group_size, prng) != (unsigned long)(modulus_size - group_size)) { + err = CRYPT_ERROR_READPRNG; + goto error; + } + + /* force magnitude */ + buf[0] |= 0xC0; + + /* force even */ + buf[modulus_size - group_size - 1] &= ~1; + + if ((err = mp_read_unsigned_bin(tmp2, buf, modulus_size - group_size)) != CRYPT_OK) { goto error; } + if ((err = mp_mul(key->q, tmp2, key->p)) != CRYPT_OK) { goto error; } + if ((err = mp_add_d(key->p, 1, key->p)) != CRYPT_OK) { goto error; } + + /* now loop until p is prime */ + for (;;) { + if ((err = mp_prime_is_prime(key->p, 8, &res)) != CRYPT_OK) { goto error; } + if (res == LTC_MP_YES) break; + + /* add 2q to p and 2 to tmp2 */ + if ((err = mp_add(tmp, key->p, key->p)) != CRYPT_OK) { goto error; } + if ((err = mp_add_d(tmp2, 2, tmp2)) != CRYPT_OK) { goto error; } + } + + /* now p = (q * tmp2) + 1 is prime, find a value g for which g^tmp2 != 1 */ + mp_set(key->g, 1); + + do { + if ((err = mp_add_d(key->g, 1, key->g)) != CRYPT_OK) { goto error; } + if ((err = mp_exptmod(key->g, tmp2, key->p, tmp)) != CRYPT_OK) { goto error; } + } while (mp_cmp_d(tmp, 1) == LTC_MP_EQ); + + /* at this point tmp generates a group of order q mod p */ + mp_exch(tmp, key->g); + + /* so now we have our DH structure, generator g, order q, modulus p + Now we need a random exponent [mod q] and it's power g^x mod p + */ + do { + if (prng_descriptor[wprng].read(buf, group_size, prng) != (unsigned long)group_size) { + err = CRYPT_ERROR_READPRNG; + goto error; + } + if ((err = mp_read_unsigned_bin(key->x, buf, group_size)) != CRYPT_OK) { goto error; } + } while (mp_cmp_d(key->x, 1) != LTC_MP_GT); + if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { goto error; } + + key->type = PK_PRIVATE; + key->qord = group_size; + +#ifdef LTC_CLEAN_STACK + zeromem(buf, LTC_MDSA_DELTA); +#endif + + err = CRYPT_OK; + goto done; +error: + mp_clear_multi(key->g, key->q, key->p, key->x, key->y, NULL); +done: + mp_clear_multi(tmp, tmp2, NULL); + XFREE(buf); + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_make_key.c,v $ */ +/* $Revision: 1.12 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/dsa/dsa_shared_secret.c b/core/lib/libtomcrypt/src/pk/dsa/dsa_shared_secret.c new file mode 100644 index 00000000000..449af93f19f --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/dsa/dsa_shared_secret.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file dsa_shared_secret.c + DSA Crypto, Tom St Denis +*/ + +#ifdef LTC_MDSA + +/** + Create a DSA shared secret between two keys + @param private_key The private DSA key (the exponent) + @param base The base of the exponentiation (allows this to be used for both encrypt and decrypt) + @param public_key The public key + @param out [out] Destination of the shared secret + @param outlen [in/out] The max size and resulting size of the shared secret + @return CRYPT_OK if successful +*/ +int dsa_shared_secret(void *private_key, void *base, + dsa_key *public_key, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x; + void *res; + int err; + + LTC_ARGCHK(private_key != NULL); + LTC_ARGCHK(public_key != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* make new point */ + if ((err = mp_init(&res)) != CRYPT_OK) { + return err; + } + + if ((err = mp_exptmod(base, private_key, public_key->p, res)) != CRYPT_OK) { + mp_clear(res); + return err; + } + + x = (unsigned long)mp_unsigned_bin_size(res); + if (*outlen < x) { + *outlen = x; + err = CRYPT_BUFFER_OVERFLOW; + goto done; + } + zeromem(out, x); + if ((err = mp_to_unsigned_bin(res, out + (x - mp_unsigned_bin_size(res)))) != CRYPT_OK) { goto done; } + + err = CRYPT_OK; + *outlen = x; +done: + mp_clear(res); + return err; +} + +#endif +/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_shared_secret.c,v $ */ +/* $Revision: 1.9 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/dsa/dsa_sign_hash.c b/core/lib/libtomcrypt/src/pk/dsa/dsa_sign_hash.c new file mode 100644 index 00000000000..4c620584fb8 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/dsa/dsa_sign_hash.c @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file dsa_sign_hash.c + DSA implementation, sign a hash, Tom St Denis +*/ + +#ifdef LTC_MDSA + +/** + Sign a hash with DSA + @param in The hash to sign + @param inlen The length of the hash to sign + @param r The "r" integer of the signature (caller must initialize with mp_init() first) + @param s The "s" integer of the signature (caller must initialize with mp_init() first) + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param key A private DSA key + @return CRYPT_OK if successful +*/ +int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen, + void *r, void *s, + prng_state *prng, int wprng, dsa_key *key) +{ + void *k, *kinv, *tmp; + unsigned char *buf; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(r != NULL); + LTC_ARGCHK(s != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + if (key->type != PK_PRIVATE) { + return CRYPT_PK_NOT_PRIVATE; + } + + /* check group order size */ + if (key->qord >= LTC_MDSA_MAX_GROUP) { + return CRYPT_INVALID_ARG; + } + + buf = XMALLOC(LTC_MDSA_MAX_GROUP); + if (buf == NULL) { + return CRYPT_MEM; + } + + /* Init our temps */ + if ((err = mp_init_multi(&k, &kinv, &tmp, NULL)) != CRYPT_OK) { goto ERRBUF; } + +retry: + + do { + /* gen random k */ + if (prng_descriptor[wprng].read(buf, key->qord, prng) != (unsigned long)key->qord) { + err = CRYPT_ERROR_READPRNG; + goto error; + } + + /* read k */ + if ((err = mp_read_unsigned_bin(k, buf, key->qord)) != CRYPT_OK) { goto error; } + + /* k > 1 ? */ + if (mp_cmp_d(k, 1) != LTC_MP_GT) { goto retry; } + + /* test gcd */ + if ((err = mp_gcd(k, key->q, tmp)) != CRYPT_OK) { goto error; } + } while (mp_cmp_d(tmp, 1) != LTC_MP_EQ); + + /* now find 1/k mod q */ + if ((err = mp_invmod(k, key->q, kinv)) != CRYPT_OK) { goto error; } + + /* now find r = g^k mod p mod q */ + if ((err = mp_exptmod(key->g, k, key->p, r)) != CRYPT_OK) { goto error; } + if ((err = mp_mod(r, key->q, r)) != CRYPT_OK) { goto error; } + + if (mp_iszero(r) == LTC_MP_YES) { goto retry; } + + /* now find s = (in + xr)/k mod q */ + if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, inlen)) != CRYPT_OK) { goto error; } + if ((err = mp_mul(key->x, r, s)) != CRYPT_OK) { goto error; } + if ((err = mp_add(s, tmp, s)) != CRYPT_OK) { goto error; } + if ((err = mp_mulmod(s, kinv, key->q, s)) != CRYPT_OK) { goto error; } + + if (mp_iszero(s) == LTC_MP_YES) { goto retry; } + + err = CRYPT_OK; +error: + mp_clear_multi(k, kinv, tmp, NULL); +ERRBUF: +#ifdef LTC_CLEAN_STACK + zeromem(buf, LTC_MDSA_MAX_GROUP); +#endif + XFREE(buf); + return err; +} + +/** + Sign a hash with DSA + @param in The hash to sign + @param inlen The length of the hash to sign + @param out [out] Where to store the signature + @param outlen [in/out] The max size and resulting size of the signature + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param key A private DSA key + @return CRYPT_OK if successful +*/ +int dsa_sign_hash(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, dsa_key *key) +{ + void *r, *s; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + if (mp_init_multi(&r, &s, NULL) != CRYPT_OK) { + return CRYPT_MEM; + } + + if ((err = dsa_sign_hash_raw(in, inlen, r, s, prng, wprng, key)) != CRYPT_OK) { + goto error; + } + + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_INTEGER, 1UL, r, + LTC_ASN1_INTEGER, 1UL, s, + LTC_ASN1_EOL, 0UL, NULL); + +error: + mp_clear_multi(r, s, NULL); + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_sign_hash.c,v $ */ +/* $Revision: 1.14 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/dsa/dsa_verify_hash.c b/core/lib/libtomcrypt/src/pk/dsa/dsa_verify_hash.c new file mode 100644 index 00000000000..4eb76e467b0 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/dsa/dsa_verify_hash.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file dsa_verify_hash.c + DSA implementation, verify a signature, Tom St Denis +*/ + + +#ifdef LTC_MDSA +/** + Verify a DSA signature + @param r DSA "r" parameter + @param s DSA "s" parameter + @param hash The hash that was signed + @param hashlen The length of the hash that was signed + @param stat [out] The result of the signature verification, 1==valid, 0==invalid + @param key The corresponding public DH key + @return CRYPT_OK if successful (even if the signature is invalid) +*/ +int dsa_verify_hash_raw( void *r, void *s, + const unsigned char *hash, unsigned long hashlen, + int *stat, dsa_key *key) +{ + void *w, *v, *u1, *u2; + int err; + + LTC_ARGCHK(r != NULL); + LTC_ARGCHK(s != NULL); + LTC_ARGCHK(stat != NULL); + LTC_ARGCHK(key != NULL); + + /* default to invalid signature */ + *stat = 0; + + /* init our variables */ + if ((err = mp_init_multi(&w, &v, &u1, &u2, NULL)) != CRYPT_OK) { + return err; + } + + /* neither r or s can be null or >q*/ + if (mp_iszero(r) == LTC_MP_YES || mp_iszero(s) == LTC_MP_YES || mp_cmp(r, key->q) != LTC_MP_LT || mp_cmp(s, key->q) != LTC_MP_LT) { + err = CRYPT_INVALID_PACKET; + goto error; + } + + /* w = 1/s mod q */ + if ((err = mp_invmod(s, key->q, w)) != CRYPT_OK) { goto error; } + + /* u1 = m * w mod q */ + if ((err = mp_read_unsigned_bin(u1, (unsigned char *)hash, hashlen)) != CRYPT_OK) { goto error; } + + if ((err = mp_mulmod(u1, w, key->q, u1)) != CRYPT_OK) { goto error; } + + /* u2 = r*w mod q */ + if ((err = mp_mulmod(r, w, key->q, u2)) != CRYPT_OK) { goto error; } + + /* v = g^u1 * y^u2 mod p mod q */ + if ((err = mp_exptmod(key->g, u1, key->p, u1)) != CRYPT_OK) { goto error; } + if ((err = mp_exptmod(key->y, u2, key->p, u2)) != CRYPT_OK) { goto error; } + if ((err = mp_mulmod(u1, u2, key->p, v)) != CRYPT_OK) { goto error; } + if ((err = mp_mod(v, key->q, v)) != CRYPT_OK) { goto error; } + + /* if r = v then we're set */ + if (mp_cmp(r, v) == LTC_MP_EQ) { + *stat = 1; + } + + err = CRYPT_OK; +error: + mp_clear_multi(w, v, u1, u2, NULL); + return err; +} + +/** + Verify a DSA signature + @param sig The signature + @param siglen The length of the signature (octets) + @param hash The hash that was signed + @param hashlen The length of the hash that was signed + @param stat [out] The result of the signature verification, 1==valid, 0==invalid + @param key The corresponding public DH key + @return CRYPT_OK if successful (even if the signature is invalid) +*/ +int dsa_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, dsa_key *key) +{ + int err; + void *r, *s; + + if ((err = mp_init_multi(&r, &s, NULL)) != CRYPT_OK) { + return CRYPT_MEM; + } + + /* decode the sequence */ + if ((err = der_decode_sequence_multi(sig, siglen, + LTC_ASN1_INTEGER, 1UL, r, + LTC_ASN1_INTEGER, 1UL, s, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* do the op */ + err = dsa_verify_hash_raw(r, s, hash, hashlen, stat, key); + +LBL_ERR: + mp_clear_multi(r, s, NULL); + return err; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_verify_hash.c,v $ */ +/* $Revision: 1.15 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/dsa/dsa_verify_key.c b/core/lib/libtomcrypt/src/pk/dsa/dsa_verify_key.c new file mode 100644 index 00000000000..c413a4e2932 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/dsa/dsa_verify_key.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file dsa_verify_key.c + DSA implementation, verify a key, Tom St Denis +*/ + +#ifdef LTC_MDSA + +/** + Verify a DSA key for validity + @param key The key to verify + @param stat [out] Result of test, 1==valid, 0==invalid + @return CRYPT_OK if successful +*/ +int dsa_verify_key(dsa_key *key, int *stat) +{ + void *tmp, *tmp2; + int res, err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(stat != NULL); + + /* default to an invalid key */ + *stat = 0; + + /* first make sure key->q and key->p are prime */ + if ((err = mp_prime_is_prime(key->q, 8, &res)) != CRYPT_OK) { + return err; + } + if (res == 0) { + return CRYPT_OK; + } + + if ((err = mp_prime_is_prime(key->p, 8, &res)) != CRYPT_OK) { + return err; + } + if (res == 0) { + return CRYPT_OK; + } + + /* now make sure that g is not -1, 0 or 1 and

g, 0) == LTC_MP_EQ || mp_cmp_d(key->g, 1) == LTC_MP_EQ) { + return CRYPT_OK; + } + if ((err = mp_init_multi(&tmp, &tmp2, NULL)) != CRYPT_OK) { return err; } + if ((err = mp_sub_d(key->p, 1, tmp)) != CRYPT_OK) { goto error; } + if (mp_cmp(tmp, key->g) == LTC_MP_EQ || mp_cmp(key->g, key->p) != LTC_MP_LT) { + err = CRYPT_OK; + goto error; + } + + /* 1 < y < p-1 */ + if (!(mp_cmp_d(key->y, 1) == LTC_MP_GT && mp_cmp(key->y, tmp) == LTC_MP_LT)) { + err = CRYPT_OK; + goto error; + } + + /* now we have to make sure that g^q = 1, and that p-1/q gives 0 remainder */ + if ((err = mp_div(tmp, key->q, tmp, tmp2)) != CRYPT_OK) { goto error; } + if (mp_iszero(tmp2) != LTC_MP_YES) { + err = CRYPT_OK; + goto error; + } + + if ((err = mp_exptmod(key->g, key->q, key->p, tmp)) != CRYPT_OK) { goto error; } + if (mp_cmp_d(tmp, 1) != LTC_MP_EQ) { + err = CRYPT_OK; + goto error; + } + + /* now we have to make sure that y^q = 1, this makes sure y \in g^x mod p */ + if ((err = mp_exptmod(key->y, key->q, key->p, tmp)) != CRYPT_OK) { goto error; } + if (mp_cmp_d(tmp, 1) != LTC_MP_EQ) { + err = CRYPT_OK; + goto error; + } + + /* at this point we are out of tests ;-( */ + err = CRYPT_OK; + *stat = 1; +error: + mp_clear_multi(tmp, tmp2, NULL); + return err; +} +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_verify_key.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/dsa/sub.mk b/core/lib/libtomcrypt/src/pk/dsa/sub.mk new file mode 100644 index 00000000000..bd1d2df438f --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/dsa/sub.mk @@ -0,0 +1,10 @@ +srcs-y += dsa_decrypt_key.c +srcs-y += dsa_encrypt_key.c +srcs-y += dsa_export.c +srcs-y += dsa_free.c +srcs-y += dsa_import.c +srcs-y += dsa_make_key.c +srcs-y += dsa_shared_secret.c +srcs-y += dsa_sign_hash.c +srcs-y += dsa_verify_hash.c +srcs-y += dsa_verify_key.c diff --git a/core/lib/libtomcrypt/src/pk/ecc/ecc.c b/core/lib/libtomcrypt/src/pk/ecc/ecc.c new file mode 100644 index 00000000000..19a35a38aa7 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/ecc/ecc.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b + * + * All curves taken from NIST recommendation paper of July 1999 + * Available at http://csrc.nist.gov/cryptval/dss.htm + */ +#include "tomcrypt.h" + +/** + @file ecc.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/* This holds the key settings. ***MUST*** be organized by size from smallest to largest. */ +const ltc_ecc_set_type ltc_ecc_sets[] = { +#ifdef ECC112 +{ + 14, + "SECP112R1", + "DB7C2ABF62E35E668076BEAD208B", + "659EF8BA043916EEDE8911702B22", + "DB7C2ABF62E35E7628DFAC6561C5", + "09487239995A5EE76B55F9C2F098", + "A89CE5AF8724C0A23E0E0FF77500" +}, +#endif +#ifdef ECC128 +{ + 16, + "SECP128R1", + "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", + "E87579C11079F43DD824993C2CEE5ED3", + "FFFFFFFE0000000075A30D1B9038A115", + "161FF7528B899B2D0C28607CA52C5B86", + "CF5AC8395BAFEB13C02DA292DDED7A83", +}, +#endif +#ifdef ECC160 +{ + 20, + "SECP160R1", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", + "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", + "0100000000000000000001F4C8F927AED3CA752257", + "4A96B5688EF573284664698968C38BB913CBFC82", + "23A628553168947D59DCC912042351377AC5FB32", +}, +#endif +#ifdef ECC192 +{ + 24, + "ECC-192", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", + "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", + "7192B95FFC8DA78631011ED6B24CDD573F977A11E794811", +}, +#endif +#ifdef ECC224 +{ + 28, + "ECC-224", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", + "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", +}, +#endif +//#ifdef ECC256 +#if 0 +{ + 32, + "ECC-256", + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", + "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", +}, +#endif +#ifdef ECC384 +{ + 48, + "ECC-384", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", + "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", +}, +#endif +#ifdef ECC521 +{ + 66, + "ECC-521", + "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", + "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", + "C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", + "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", +}, +#endif +{ + 0, + NULL, NULL, NULL, NULL, NULL, NULL +} +}; + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc.c,v $ */ +/* $Revision: 1.40 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c b/core/lib/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c new file mode 100644 index 00000000000..6f6df029b03 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b + * + * All curves taken from NIST recommendation paper of July 1999 + * Available at http://csrc.nist.gov/cryptval/dss.htm + */ +#include "tomcrypt.h" + +/** + @file ecc_ansi_x963_export.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** ECC X9.63 (Sec. 4.3.6) uncompressed export + @param key Key to export + @param out [out] destination of export + @param outlen [in/out] Length of destination and final output size + Return CRYPT_OK on success +*/ +int ecc_ansi_x963_export(ecc_key *key, unsigned char *out, unsigned long *outlen) +{ + unsigned char buf[ECC_BUF_SIZE]; + unsigned long numlen; + + LTC_ARGCHK(key != NULL); + 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; + + if (*outlen < (1 + 2*numlen)) { + *outlen = 1 + 2*numlen; + return CRYPT_BUFFER_OVERFLOW; + } + + /* store byte 0x04 */ + out[0] = 0x04; + + /* pad and store x */ + zeromem(buf, sizeof(buf)); + mp_to_unsigned_bin(key->pubkey.x, buf + (numlen - mp_unsigned_bin_size(key->pubkey.x))); + XMEMCPY(out+1, buf, numlen); + + /* pad and store y */ + zeromem(buf, sizeof(buf)); + mp_to_unsigned_bin(key->pubkey.y, buf + (numlen - mp_unsigned_bin_size(key->pubkey.y))); + XMEMCPY(out+1+numlen, buf, numlen); + + *outlen = 1 + 2*numlen; + return CRYPT_OK; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c b/core/lib/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c new file mode 100644 index 00000000000..cafbd0701e5 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b + * + * All curves taken from NIST recommendation paper of July 1999 + * Available at http://csrc.nist.gov/cryptval/dss.htm + */ +#include "tomcrypt.h" + +/** + @file ecc_ansi_x963_import.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** Import an ANSI X9.63 format public key + @param in The input data to read + @param inlen The length of the input data + @param key [out] destination to store imported key \ +*/ +int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *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 x, err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + /* must be odd */ + if ((inlen & 1) == 0) { + 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; + } + + if ((err = mp_read_unsigned_bin(key->pubkey.y, (unsigned char *)in+1+((inlen-1)>>1), (inlen-1)>>1)) != CRYPT_OK) { + goto error; + } + if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto error; } + + if (dp == NULL) { + /* 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 = <c_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; + + /* 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 + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c,v $ */ +/* $Revision: 1.11 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c b/core/lib/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c new file mode 100644 index 00000000000..b928dce19ad --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b + * + * All curves taken from NIST recommendation paper of July 1999 + * Available at http://csrc.nist.gov/cryptval/dss.htm + */ +#include "tomcrypt.h" + +/** + @file ecc_decrypt_key.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** + Decrypt an ECC encrypted key + @param in The ciphertext + @param inlen The length of the ciphertext (octets) + @param out [out] The plaintext + @param outlen [in/out] The max size and resulting size of the plaintext + @param key The corresponding private ECC key + @return CRYPT_OK if successful +*/ +int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + ecc_key *key) +{ + unsigned char *ecc_shared, *skey, *pub_expt; + unsigned long x, y, hashOID[32]; + int hash, err; + ecc_key pubkey; + ltc_asn1_list decode[3]; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + /* right key type? */ + if (key->type != PK_PRIVATE) { + return CRYPT_PK_NOT_PRIVATE; + } + + /* decode to find out hash */ + LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, sizeof(hashOID)/sizeof(hashOID[0])); + + if ((err = der_decode_sequence(in, inlen, decode, 1)) != CRYPT_OK) { + return err; + } + + hash = find_hash_oid(hashOID, decode[0].size); + if (hash_is_valid(hash) != CRYPT_OK) { + return CRYPT_INVALID_PACKET; + } + + /* we now have the hash! */ + + /* allocate memory */ + pub_expt = XMALLOC(ECC_BUF_SIZE); + ecc_shared = XMALLOC(ECC_BUF_SIZE); + skey = XMALLOC(MAXBLOCKSIZE); + if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) { + if (pub_expt != NULL) { + XFREE(pub_expt); + } + if (ecc_shared != NULL) { + XFREE(ecc_shared); + } + if (skey != NULL) { + XFREE(skey); + } + return CRYPT_MEM; + } + LTC_SET_ASN1(decode, 1, LTC_ASN1_OCTET_STRING, pub_expt, ECC_BUF_SIZE); + LTC_SET_ASN1(decode, 2, LTC_ASN1_OCTET_STRING, skey, MAXBLOCKSIZE); + + /* read the structure in now */ + if ((err = der_decode_sequence(in, inlen, decode, 3)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* import ECC key from packet */ + if ((err = ecc_import(decode[1].data, decode[1].size, &pubkey)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* make shared key */ + x = ECC_BUF_SIZE; + if ((err = ecc_shared_secret(key, &pubkey, ecc_shared, &x)) != CRYPT_OK) { + ecc_free(&pubkey); + goto LBL_ERR; + } + ecc_free(&pubkey); + + y = MIN(ECC_BUF_SIZE, MAXBLOCKSIZE); + if ((err = hash_memory(hash, ecc_shared, x, ecc_shared, &y)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* ensure the hash of the shared secret is at least as big as the encrypt itself */ + if (decode[2].size > y) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + /* avoid buffer overflow */ + if (*outlen < decode[2].size) { + *outlen = decode[2].size; + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + + /* Decrypt the key */ + for (x = 0; x < decode[2].size; x++) { + out[x] = skey[x] ^ ecc_shared[x]; + } + *outlen = x; + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(pub_expt, ECC_BUF_SIZE); + zeromem(ecc_shared, ECC_BUF_SIZE); + zeromem(skey, MAXBLOCKSIZE); +#endif + + XFREE(pub_expt); + XFREE(ecc_shared); + XFREE(skey); + + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c b/core/lib/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c new file mode 100644 index 00000000000..f37f3742e45 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b + * + * All curves taken from NIST recommendation paper of July 1999 + * Available at http://csrc.nist.gov/cryptval/dss.htm + */ +#include "tomcrypt.h" + +/** + @file ecc_encrypt_key.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** + Encrypt a symmetric key with ECC + @param in The symmetric key you want to encrypt + @param inlen The length of the key to encrypt (octets) + @param out [out] The destination for the ciphertext + @param outlen [in/out] The max size and resulting size of the ciphertext + @param prng An active PRNG state + @param wprng The index of the PRNG you wish to use + @param hash The index of the hash you want to use + @param key The ECC key you want to encrypt to + @return CRYPT_OK if successful +*/ +int ecc_encrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, int hash, + ecc_key *key) +{ + unsigned char *pub_expt, *ecc_shared, *skey; + ecc_key pubkey; + unsigned long x, y, pubkeysize; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + /* check that wprng/cipher/hash are not invalid */ + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + if (inlen > hash_descriptor[hash].hashsize) { + return CRYPT_INVALID_HASH; + } + + /* make a random key and export the public copy */ + if ((err = ecc_make_key_ex(prng, wprng, &pubkey, key->dp)) != CRYPT_OK) { + return err; + } + + pub_expt = XMALLOC(ECC_BUF_SIZE); + ecc_shared = XMALLOC(ECC_BUF_SIZE); + skey = XMALLOC(MAXBLOCKSIZE); + if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) { + if (pub_expt != NULL) { + XFREE(pub_expt); + } + if (ecc_shared != NULL) { + XFREE(ecc_shared); + } + if (skey != NULL) { + XFREE(skey); + } + ecc_free(&pubkey); + return CRYPT_MEM; + } + + pubkeysize = ECC_BUF_SIZE; + if ((err = ecc_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) { + ecc_free(&pubkey); + goto LBL_ERR; + } + + /* make random key */ + x = ECC_BUF_SIZE; + if ((err = ecc_shared_secret(&pubkey, key, ecc_shared, &x)) != CRYPT_OK) { + ecc_free(&pubkey); + goto LBL_ERR; + } + ecc_free(&pubkey); + y = MAXBLOCKSIZE; + if ((err = hash_memory(hash, ecc_shared, x, skey, &y)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* Encrypt key */ + for (x = 0; x < inlen; x++) { + skey[x] ^= in[x]; + } + + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash].OIDlen, hash_descriptor[hash].OID, + LTC_ASN1_OCTET_STRING, pubkeysize, pub_expt, + LTC_ASN1_OCTET_STRING, inlen, skey, + LTC_ASN1_EOL, 0UL, NULL); + +LBL_ERR: +#ifdef LTC_CLEAN_STACK + /* clean up */ + zeromem(pub_expt, ECC_BUF_SIZE); + zeromem(ecc_shared, ECC_BUF_SIZE); + zeromem(skey, MAXBLOCKSIZE); +#endif + + XFREE(skey); + XFREE(ecc_shared); + XFREE(pub_expt); + + return err; +} + +#endif +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/ecc/ecc_export.c b/core/lib/libtomcrypt/src/pk/ecc/ecc_export.c new file mode 100644 index 00000000000..70baedd75fd --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/ecc/ecc_export.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b + * + * All curves taken from NIST recommendation paper of July 1999 + * Available at http://csrc.nist.gov/cryptval/dss.htm + */ +#include "tomcrypt.h" + +/** + @file ecc_export.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** + Export an ECC key as a binary packet + @param out [out] Destination for the key + @param outlen [in/out] Max size and resulting size of the exported key + @param type The type of key you want to export (PK_PRIVATE or PK_PUBLIC) + @param key The key to export + @return CRYPT_OK if successful +*/ +int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key) +{ + int err; + unsigned char flags[1]; + unsigned long key_size; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + /* type valid? */ + 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; + } + + /* we store the NIST byte size */ + key_size = key->dp->size; + + if (type == PK_PRIVATE) { + flags[0] = 1; + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_SHORT_INTEGER, 1UL, &key_size, + LTC_ASN1_INTEGER, 1UL, key->pubkey.x, + LTC_ASN1_INTEGER, 1UL, key->pubkey.y, + LTC_ASN1_INTEGER, 1UL, key->k, + LTC_ASN1_EOL, 0UL, NULL); + } else { + flags[0] = 0; + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_SHORT_INTEGER, 1UL, &key_size, + LTC_ASN1_INTEGER, 1UL, key->pubkey.x, + LTC_ASN1_INTEGER, 1UL, key->pubkey.y, + LTC_ASN1_EOL, 0UL, NULL); + } + + return err; +} + +#endif +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_export.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/ecc/ecc_free.c b/core/lib/libtomcrypt/src/pk/ecc/ecc_free.c new file mode 100644 index 00000000000..5de73ca0159 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/ecc/ecc_free.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b + * + * All curves taken from NIST recommendation paper of July 1999 + * Available at http://csrc.nist.gov/cryptval/dss.htm + */ +#include "tomcrypt.h" + +/** + @file ecc_free.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** + Free an ECC key from memory + @param key The key you wish to free +*/ +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); +} + +#endif +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_free.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/ecc/ecc_get_size.c b/core/lib/libtomcrypt/src/pk/ecc/ecc_get_size.c new file mode 100644 index 00000000000..5e4e382df97 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/ecc/ecc_get_size.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b + * + * All curves taken from NIST recommendation paper of July 1999 + * Available at http://csrc.nist.gov/cryptval/dss.htm + */ +#include "tomcrypt.h" + +/** + @file ecc_get_size.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** + Get the size of an ECC key + @param key The key to get the size of + @return The size (octets) of the key or INT_MAX on error +*/ +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() */ +} + +#endif +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_get_size.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/ecc/ecc_import.c b/core/lib/libtomcrypt/src/pk/ecc/ecc_import.c new file mode 100644 index 00000000000..41b3fe514d5 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/ecc/ecc_import.c @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b + * + * All curves taken from NIST recommendation paper of July 1999 + * Available at http://csrc.nist.gov/cryptval/dss.htm + */ +#include "tomcrypt.h" + +/** + @file ecc_import.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +static int is_point(ecc_key *key) +{ + void *prime, *b, *t1, *t2; + int err; + + if ((err = mp_init_multi(&prime, &b, &t1, &t2, NULL)) != CRYPT_OK) { + return err; + } + + /* load prime and b */ + if ((err = mp_read_radix(prime, key->dp->prime, 16)) != CRYPT_OK) { goto error; } + if ((err = mp_read_radix(b, key->dp->B, 16)) != CRYPT_OK) { goto error; } + + /* compute y^2 */ + if ((err = mp_sqr(key->pubkey.y, t1)) != CRYPT_OK) { goto error; } + + /* compute x^3 */ + if ((err = mp_sqr(key->pubkey.x, t2)) != CRYPT_OK) { goto error; } + if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) { goto error; } + if ((err = mp_mul(key->pubkey.x, t2, t2)) != CRYPT_OK) { goto error; } + + /* compute y^2 - x^3 */ + if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) { goto error; } + + /* compute y^2 - x^3 + 3x */ + if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; } + if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; } + if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; } + if ((err = mp_mod(t1, prime, t1)) != CRYPT_OK) { goto error; } + while (mp_cmp_d(t1, 0) == LTC_MP_LT) { + if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) { goto error; } + } + while (mp_cmp(t1, prime) != LTC_MP_LT) { + if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) { goto error; } + } + + /* compare to b */ + if (mp_cmp(t1, b) != LTC_MP_EQ) { + err = CRYPT_INVALID_PACKET; + } else { + err = CRYPT_OK; + } + +error: + mp_clear_multi(prime, b, t1, t2, NULL); + return err; +} + +/** + Import an ECC key from a binary packet + @param in The packet to import + @param inlen The length of the packet + @param key [out] The destination of the import + @return CRYPT_OK if successful, upon error all allocated memory will be freed +*/ +int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key) +{ + return ecc_import_ex(in, inlen, key, NULL); +} + +/** + Import an ECC key from a binary packet, using user supplied domain params rather than one of the NIST ones + @param in The packet to import + @param inlen The length of the packet + @param key [out] The destination of the import + @param dp pointer to user supplied params; must be the same as the params used when exporting + @return CRYPT_OK if successful, upon error all allocated memory will be freed +*/ +int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_set_type *dp) +{ + unsigned long key_size; + unsigned char flags[1]; + int err; + + LTC_ARGCHK(in != NULL); + 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 */ + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_BIT_STRING, 1UL, &flags, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto done; + } + + + if (flags[0] == 1) { + /* private key */ + key->type = PK_PRIVATE; + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_SHORT_INTEGER, 1UL, &key_size, + LTC_ASN1_INTEGER, 1UL, key->pubkey.x, + LTC_ASN1_INTEGER, 1UL, key->pubkey.y, + LTC_ASN1_INTEGER, 1UL, key->k, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto done; + } + } else { + /* public key */ + key->type = PK_PUBLIC; + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_SHORT_INTEGER, 1UL, &key_size, + LTC_ASN1_INTEGER, 1UL, key->pubkey.x, + LTC_ASN1_INTEGER, 1UL, key->pubkey.y, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + 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 = <c_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 = is_point(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); + return err; +} +#endif +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_import.c,v $ */ +/* $Revision: 1.13 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/ecc/ecc_make_key.c b/core/lib/libtomcrypt/src/pk/ecc/ecc_make_key.c new file mode 100644 index 00000000000..c5a59eb3459 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/ecc/ecc_make_key.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b + * + * All curves taken from NIST recommendation paper of July 1999 + * Available at http://csrc.nist.gov/cryptval/dss.htm + */ +#include "tomcrypt.h" + +/** + @file ecc_make_key.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** + Make a new ECC key + @param prng An active PRNG state + @param wprng The index of the PRNG you wish to use + @param keysize The keysize for the new key (in octets from 20 to 65 bytes) + @param key [out] Destination of the newly created key + @return CRYPT_OK if successful, upon error all allocated memory will be freed +*/ +int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key) +{ + int x, 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, <c_ecc_sets[x]); + key->idx = x; + return err; +} + +int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set_type *dp) +{ + int err; + ecc_point *base; + void *prime, *order; + unsigned char *buf; + int keysize; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + LTC_ARGCHK(dp != NULL); + + /* 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, 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; } + + /* the key should be smaller than the order of base point */ + if (mp_cmp(key->k, order) != LTC_MP_LT) { + if((err = mp_mod(key->k, order, key->k)) != CRYPT_OK) { goto errkey; } + } + /* make the public key */ + if ((err = ltc_mp.ecc_ptmul(key->k, base, &key->pubkey, prime, 1)) != CRYPT_OK) { goto errkey; } + key->type = PK_PRIVATE; + + /* free up ram */ + err = CRYPT_OK; + goto cleanup; +errkey: + mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); +cleanup: + ltc_ecc_del_point(base); + mp_clear_multi(prime, order, NULL); +ERR_BUF: +#ifdef LTC_CLEAN_STACK + zeromem(buf, ECC_MAXSIZE); +#endif + XFREE(buf); + return err; +} + +#endif +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_make_key.c,v $ */ +/* $Revision: 1.13 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/ecc/ecc_shared_secret.c b/core/lib/libtomcrypt/src/pk/ecc/ecc_shared_secret.c new file mode 100644 index 00000000000..5c0b563a693 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/ecc/ecc_shared_secret.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b + * + * All curves taken from NIST recommendation paper of July 1999 + * Available at http://csrc.nist.gov/cryptval/dss.htm + */ +#include "tomcrypt.h" + +/** + @file ecc_shared_secret.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** + Create an ECC shared secret between two keys + @param private_key The private ECC key + @param public_key The public key + @param out [out] Destination of the shared secret (Conforms to EC-DH from ANSI X9.63) + @param outlen [in/out] The max size and resulting size of the shared secret + @return CRYPT_OK if successful +*/ +int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x; + ecc_point *result; + void *prime; + int err; + + LTC_ARGCHK(private_key != NULL); + LTC_ARGCHK(public_key != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* type valid? */ + if (private_key->type != PK_PRIVATE) { + 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; + } + + 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(&prime)) != CRYPT_OK) { + ltc_ecc_del_point(result); + return err; + } + + if ((err = mp_read_radix(prime, (char *)private_key->dp->prime, 16)) != CRYPT_OK) { goto done; } + if ((err = ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, prime, 1)) != CRYPT_OK) { goto done; } + + x = (unsigned long)mp_unsigned_bin_size(prime); + if (*outlen < x) { + *outlen = x; + err = CRYPT_BUFFER_OVERFLOW; + 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; } + + err = CRYPT_OK; + *outlen = x; +done: + mp_clear(prime); + ltc_ecc_del_point(result); + return err; +} + +#endif +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_shared_secret.c,v $ */ +/* $Revision: 1.10 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/ecc/ecc_sign_hash.c b/core/lib/libtomcrypt/src/pk/ecc/ecc_sign_hash.c new file mode 100644 index 00000000000..8c423616e4f --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/ecc/ecc_sign_hash.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b + * + * All curves taken from NIST recommendation paper of July 1999 + * Available at http://csrc.nist.gov/cryptval/dss.htm + */ +#include "tomcrypt.h" + +/** + @file ecc_sign_hash.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** + Sign a message digest + @param in The message digest to sign + @param inlen The length of the digest + @param out [out] The destination for the signature + @param outlen [in/out] The max size and resulting size of the signature + @param prng An active PRNG state + @param wprng The index of the PRNG you wish to use + @param key A private ECC key + @return CRYPT_OK if successful +*/ +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) +{ + ecc_key pubkey; + void *r, *s, *e, *p; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + /* is this a private key? */ + if (key->type != PK_PRIVATE) { + 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; + } + + /* get the hash and load it as a bignum into 'e' */ + /* init the bignums */ + if ((err = mp_init_multi(&r, &s, &p, &e, NULL)) != CRYPT_OK) { + return err; + } + if ((err = mp_read_radix(p, (char *)key->dp->order, 16)) != CRYPT_OK) { goto errnokey; } + if ((err = mp_read_unsigned_bin(e, (unsigned char *)in, (int)inlen)) != CRYPT_OK) { goto errnokey; } + + /* 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; + } + + /* find r = x1 mod n */ + if ((err = mp_mod(pubkey.pubkey.x, p, r)) != CRYPT_OK) { goto error; } + + if (mp_iszero(r) == LTC_MP_YES) { + ecc_free(&pubkey); + } 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 */ + if ((err = mp_add(e, s, s)) != CRYPT_OK) { goto error; } /* s = e + xr */ + if ((err = mp_mod(s, p, s)) != CRYPT_OK) { goto error; } /* s = e + xr */ + if ((err = mp_mulmod(s, pubkey.k, p, s)) != CRYPT_OK) { goto error; } /* s = (e + xr)/k */ + ecc_free(&pubkey); + if (mp_iszero(s) == LTC_MP_NO) { + break; + } + } + } + + /* store as SEQUENCE { r, s -- integer } */ + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_INTEGER, 1UL, r, + LTC_ASN1_INTEGER, 1UL, s, + LTC_ASN1_EOL, 0UL, NULL); + goto errnokey; +error: + ecc_free(&pubkey); +errnokey: + mp_clear_multi(r, s, p, e, NULL); + return err; +} + +#endif +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_sign_hash.c,v $ */ +/* $Revision: 1.11 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/ecc/ecc_sizes.c b/core/lib/libtomcrypt/src/pk/ecc/ecc_sizes.c new file mode 100644 index 00000000000..da8a45db8b3 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/ecc/ecc_sizes.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b + * + * All curves taken from NIST recommendation paper of July 1999 + * Available at http://csrc.nist.gov/cryptval/dss.htm + */ +#include "tomcrypt.h" + +/** + @file ecc_sizes.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +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; + } + } +} + +#endif +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_sizes.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/ecc/ecc_test.c b/core/lib/libtomcrypt/src/pk/ecc/ecc_test.c new file mode 100644 index 00000000000..288fb8e8ba3 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/ecc/ecc_test.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b + * + * All curves taken from NIST recommendation paper of July 1999 + * Available at http://csrc.nist.gov/cryptval/dss.htm + */ +#include "tomcrypt.h" + +/** + @file ecc_test.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** + Perform on the ECC system + @return CRYPT_OK if successful +*/ +int ecc_test(void) +{ + void *modulus, *order; + ecc_point *G, *GG; + int i, err, primality; + + if ((err = mp_init_multi(&modulus, &order, NULL)) != CRYPT_OK) { + return err; + } + + G = ltc_ecc_new_point(); + GG = ltc_ecc_new_point(); + if (G == NULL || GG == NULL) { + mp_clear_multi(modulus, order, NULL); + ltc_ecc_del_point(G); + ltc_ecc_del_point(GG); + return CRYPT_MEM; + } + + for (i = 0; ltc_ecc_sets[i].size; i++) { + #if 0 + printf("Testing %d\n", ltc_ecc_sets[i].size); + #endif + if ((err = mp_read_radix(modulus, (char *)ltc_ecc_sets[i].prime, 16)) != CRYPT_OK) { goto done; } + if ((err = mp_read_radix(order, (char *)ltc_ecc_sets[i].order, 16)) != CRYPT_OK) { goto done; } + + /* is prime actually prime? */ + if ((err = mp_prime_is_prime(modulus, 8, &primality)) != CRYPT_OK) { goto done; } + if (primality == 0) { + err = CRYPT_PK_INVALID_SYSTEM; + goto done; + } + + /* is order prime ? */ + if ((err = mp_prime_is_prime(order, 8, &primality)) != CRYPT_OK) { goto done; } + if (primality == 0) { + err = CRYPT_PK_TYPE_MISMATCH; + goto done; + } + + if ((err = mp_read_radix(G->x, (char *)ltc_ecc_sets[i].Gx, 16)) != CRYPT_OK) { goto done; } + if ((err = mp_read_radix(G->y, (char *)ltc_ecc_sets[i].Gy, 16)) != CRYPT_OK) { goto done; } + mp_set(G->z, 1); + + /* then we should have G == (order + 1)G */ + if ((err = mp_add_d(order, 1, order)) != CRYPT_OK) { goto done; } + if ((err = ltc_mp.ecc_ptmul(order, G, GG, modulus, 1)) != CRYPT_OK) { goto done; } + if (mp_cmp(G->x, GG->x) != LTC_MP_EQ || mp_cmp(G->y, GG->y) != LTC_MP_EQ) { + err = CRYPT_FAIL_TESTVECTOR; + goto done; + } + } + err = CRYPT_OK; +done: + ltc_ecc_del_point(GG); + ltc_ecc_del_point(G); + mp_clear_multi(order, modulus, NULL); + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_test.c,v $ */ +/* $Revision: 1.12 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/ecc/ecc_verify_hash.c b/core/lib/libtomcrypt/src/pk/ecc/ecc_verify_hash.c new file mode 100644 index 00000000000..5528231b4ea --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/ecc/ecc_verify_hash.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b + * + * All curves taken from NIST recommendation paper of July 1999 + * Available at http://csrc.nist.gov/cryptval/dss.htm + */ +#include "tomcrypt.h" + +/** + @file ecc_verify_hash.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/* verify + * + * w = s^-1 mod n + * u1 = xw + * u2 = rw + * X = u1*G + u2*Q + * v = X_x1 mod n + * accept if v == r + */ + +/** + Verify an ECC signature + @param sig The signature to verify + @param siglen The length of the signature (octets) + @param hash The hash (message digest) that was signed + @param hashlen The length of the hash (octets) + @param stat Result of signature, 1==valid, 0==invalid + @param key The corresponding public ECC key + @return CRYPT_OK if successful (even if the signature is not valid) +*/ +int ecc_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, ecc_key *key) +{ + ecc_point *mG, *mQ; + void *r, *s, *v, *w, *u1, *u2, *e, *p, *m; + void *mp; + int err; + + LTC_ARGCHK(sig != NULL); + LTC_ARGCHK(hash != NULL); + LTC_ARGCHK(stat != NULL); + LTC_ARGCHK(key != NULL); + + /* 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, NULL)) != CRYPT_OK) { + return CRYPT_MEM; + } + + /* allocate points */ + mG = ltc_ecc_new_point(); + mQ = ltc_ecc_new_point(); + if (mQ == NULL || mG == NULL) { + err = CRYPT_MEM; + goto error; + } + + /* parse header */ + if ((err = der_decode_sequence_multi(sig, siglen, + 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; } + + /* check for zero */ + if (mp_iszero(r) || mp_iszero(s) || mp_cmp(r, p) != LTC_MP_LT || mp_cmp(s, p) != LTC_MP_LT) { + err = CRYPT_INVALID_PACKET; + goto error; + } + + /* read hash */ + if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, (int)hashlen)) != CRYPT_OK) { goto error; } + + /* w = s^-1 mod n */ + if ((err = mp_invmod(s, p, w)) != CRYPT_OK) { goto error; } + + /* u1 = ew */ + if ((err = mp_mulmod(e, w, p, u1)) != CRYPT_OK) { goto error; } + + /* u2 = rw */ + 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->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; } + + /* compute u1*mG + u2*mQ = mG */ + if (ltc_mp.ecc_mul2add == NULL) { + if ((err = ltc_mp.ecc_ptmul(u1, mG, mG, m, 0)) != CRYPT_OK) { goto error; } + if ((err = ltc_mp.ecc_ptmul(u2, mQ, mQ, m, 0)) != CRYPT_OK) { goto error; } + + /* find the montgomery mp */ + if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK) { goto error; } + + /* add them */ + if ((err = ltc_mp.ecc_ptadd(mQ, mG, mG, m, mp)) != CRYPT_OK) { goto error; } + + /* reduce */ + 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, m)) != CRYPT_OK) { goto error; } + } + + /* v = X_x1 mod n */ + if ((err = mp_mod(mG->x, p, v)) != CRYPT_OK) { goto error; } + + /* does v == r */ + if (mp_cmp(v, r) == LTC_MP_EQ) { + *stat = 1; + } + + /* 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, NULL); + if (mp != NULL) { + mp_montgomery_free(mp); + } + return err; +} + +#endif +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_verify_hash.c,v $ */ +/* $Revision: 1.14 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_is_valid_idx.c b/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_is_valid_idx.c new file mode 100644 index 00000000000..25092730102 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_is_valid_idx.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b + * + * All curves taken from NIST recommendation paper of July 1999 + * Available at http://csrc.nist.gov/cryptval/dss.htm + */ +#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 +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_is_valid_idx.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_map.c b/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_map.c new file mode 100644 index 00000000000..7f5447abad0 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_map.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b + * + * All curves taken from NIST recommendation paper of July 1999 + * Available at http://csrc.nist.gov/cryptval/dss.htm + */ +#include "tomcrypt.h" + +/** + @file ltc_ecc_map.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** + Map a projective jacbobian point back to affine space + @param P [in/out] The point to map + @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_map(ecc_point *P, void *modulus, void *mp) +{ + void *t1, *t2; + int err; + + LTC_ARGCHK(P != NULL); + LTC_ARGCHK(modulus != NULL); + LTC_ARGCHK(mp != NULL); + + if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) { + return CRYPT_MEM; + } + + /* first map z back to normal */ + if ((err = mp_montgomery_reduce(P->z, modulus, mp)) != CRYPT_OK) { goto done; } + + /* get 1/z */ + if ((err = mp_invmod(P->z, modulus, t1)) != CRYPT_OK) { goto done; } + + /* get 1/z^2 and 1/z^3 */ + if ((err = mp_sqr(t1, t2)) != CRYPT_OK) { goto done; } + if ((err = mp_mod(t2, modulus, t2)) != CRYPT_OK) { goto done; } + if ((err = mp_mul(t1, t2, t1)) != CRYPT_OK) { goto done; } + if ((err = mp_mod(t1, modulus, t1)) != CRYPT_OK) { goto done; } + + /* multiply against x/y */ + if ((err = mp_mul(P->x, t2, P->x)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(P->x, modulus, mp)) != CRYPT_OK) { goto done; } + if ((err = mp_mul(P->y, t1, P->y)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(P->y, modulus, mp)) != CRYPT_OK) { goto done; } + if ((err = mp_set(P->z, 1)) != CRYPT_OK) { goto done; } + + err = CRYPT_OK; +done: + mp_clear_multi(t1, t2, NULL); + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_map.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c b/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c new file mode 100644 index 00000000000..dc4cb6bc561 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b + * + * All curves taken from NIST recommendation paper of July 1999 + * Available at http://csrc.nist.gov/cryptval/dss.htm + */ +#include "tomcrypt.h" + +/** + @file ltc_ecc_mul2add.c + ECC Crypto, Shamir's Trick, Tom St Denis +*/ + +#ifdef LTC_MECC + +#ifdef LTC_ECC_SHAMIR + +/** Computes kA*A + kB*B = C using Shamir's Trick + @param A First point to multiply + @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 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 *modulus) +{ + ecc_point *precomp[16]; + unsigned bitbufA, bitbufB, lenA, lenB, len, x, y, nA, nB, nibble; + unsigned char *tA, *tB; + int err, first; + void *mp, *mu; + + /* argchks */ + LTC_ARGCHK(A != NULL); + LTC_ARGCHK(B != NULL); + LTC_ARGCHK(C != NULL); + LTC_ARGCHK(kA != NULL); + LTC_ARGCHK(kB != NULL); + LTC_ARGCHK(modulus != NULL); + + /* allocate memory */ + tA = XCALLOC(1, ECC_BUF_SIZE); + if (tA == NULL) { + return CRYPT_MEM; + } + tB = XCALLOC(1, ECC_BUF_SIZE); + if (tB == NULL) { + XFREE(tA); + return CRYPT_MEM; + } + + /* get sizes */ + lenA = mp_unsigned_bin_size(kA); + lenB = mp_unsigned_bin_size(kB); + len = MAX(lenA, lenB); + + /* sanity check */ + if ((lenA > ECC_BUF_SIZE) || (lenB > ECC_BUF_SIZE)) { + err = CRYPT_INVALID_ARG; + goto ERR_T; + } + + /* extract and justify kA */ + mp_to_unsigned_bin(kA, (len - lenA) + tA); + + /* extract and justify kB */ + mp_to_unsigned_bin(kB, (len - lenB) + tB); + + /* allocate the table */ + for (x = 0; x < 16; x++) { + precomp[x] = ltc_ecc_new_point(); + if (precomp[x] == NULL) { + for (y = 0; y < x; ++y) { + ltc_ecc_del_point(precomp[y]); + } + err = CRYPT_MEM; + goto ERR_T; + } + } + + /* init montgomery reduction */ + if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { + goto ERR_P; + } + if ((err = mp_init(&mu)) != CRYPT_OK) { + goto ERR_MP; + } + if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { + goto ERR_MU; + } + + /* copy ones ... */ + if ((err = mp_mulmod(A->x, mu, modulus, precomp[1]->x)) != CRYPT_OK) { goto ERR_MU; } + if ((err = mp_mulmod(A->y, mu, modulus, precomp[1]->y)) != CRYPT_OK) { goto ERR_MU; } + if ((err = mp_mulmod(A->z, mu, modulus, precomp[1]->z)) != CRYPT_OK) { goto ERR_MU; } + + if ((err = mp_mulmod(B->x, mu, modulus, precomp[1<<2]->x)) != CRYPT_OK) { goto ERR_MU; } + if ((err = mp_mulmod(B->y, mu, modulus, precomp[1<<2]->y)) != CRYPT_OK) { goto ERR_MU; } + if ((err = mp_mulmod(B->z, mu, modulus, precomp[1<<2]->z)) != CRYPT_OK) { goto ERR_MU; } + + /* precomp [i,0](A + B) table */ + if ((err = ltc_mp.ecc_ptdbl(precomp[1], precomp[2], modulus, mp)) != CRYPT_OK) { goto ERR_MU; } + if ((err = ltc_mp.ecc_ptadd(precomp[1], precomp[2], precomp[3], modulus, mp)) != CRYPT_OK) { goto ERR_MU; } + + /* precomp [0,i](A + B) table */ + if ((err = ltc_mp.ecc_ptdbl(precomp[1<<2], precomp[2<<2], modulus, mp)) != CRYPT_OK) { goto ERR_MU; } + if ((err = ltc_mp.ecc_ptadd(precomp[1<<2], precomp[2<<2], precomp[3<<2], modulus, mp)) != CRYPT_OK) { goto ERR_MU; } + + /* precomp [i,j](A + B) table (i != 0, j != 0) */ + for (x = 1; x < 4; x++) { + for (y = 1; y < 4; y++) { + if ((err = ltc_mp.ecc_ptadd(precomp[x], precomp[(y<<2)], precomp[x+(y<<2)], modulus, mp)) != CRYPT_OK) { goto ERR_MU; } + } + } + + nibble = 3; + first = 1; + bitbufA = tA[0]; + bitbufB = tB[0]; + + /* for every byte of the multiplicands */ + for (x = -1;; ) { + /* grab a nibble */ + if (++nibble == 4) { + ++x; if (x == len) break; + bitbufA = tA[x]; + bitbufB = tB[x]; + nibble = 0; + } + + /* extract two bits from both, shift/update */ + nA = (bitbufA >> 6) & 0x03; + nB = (bitbufB >> 6) & 0x03; + bitbufA = (bitbufA << 2) & 0xFF; + bitbufB = (bitbufB << 2) & 0xFF; + + /* if both zero, if first, continue */ + if ((nA == 0) && (nB == 0) && (first == 1)) { + continue; + } + + /* double twice, only if this isn't the first */ + if (first == 0) { + /* double twice */ + if ((err = ltc_mp.ecc_ptdbl(C, C, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } + if ((err = ltc_mp.ecc_ptdbl(C, C, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } + } + + /* if not both zero */ + if ((nA != 0) || (nB != 0)) { + if (first == 1) { + /* if first, copy from table */ + first = 0; + if ((err = mp_copy(precomp[nA + (nB<<2)]->x, C->x)) != CRYPT_OK) { goto ERR_MU; } + if ((err = mp_copy(precomp[nA + (nB<<2)]->y, C->y)) != CRYPT_OK) { goto ERR_MU; } + if ((err = mp_copy(precomp[nA + (nB<<2)]->z, C->z)) != CRYPT_OK) { goto ERR_MU; } + } else { + /* if not first, add from table */ + if ((err = ltc_mp.ecc_ptadd(C, precomp[nA + (nB<<2)], C, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } + } + } + } + + /* reduce to affine */ + err = ltc_ecc_map(C, modulus, mp); + + /* clean up */ +ERR_MU: + mp_clear(mu); +ERR_MP: + mp_montgomery_free(mp); +ERR_P: + for (x = 0; x < 16; x++) { + ltc_ecc_del_point(precomp[x]); + } +ERR_T: +#ifdef LTC_CLEAN_STACK + zeromem(tA, ECC_BUF_SIZE); + zeromem(tB, ECC_BUF_SIZE); +#endif + XFREE(tA); + XFREE(tB); + + return err; +} + +#endif +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c b/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c new file mode 100644 index 00000000000..23118508205 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c @@ -0,0 +1,450 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b + * + * All curves taken from NIST recommendation paper of July 1999 + * Available at http://csrc.nist.gov/cryptval/dss.htm + */ +#include "tomcrypt.h" + +/** + @file ltc_ecc_mulmod.c + ECC Crypto, Tom St Denis + */ + +#ifdef LTC_MECC +#ifndef LTC_ECC_TIMING_RESISTANT + +#if 0 + +/* size of sliding window, don't change this! */ +#define WINSIZE 4 + +/** + Perform a point multiplication + @param k The scalar to multiply by + @param G The base point + @param R [out] Destination for kG + @param modulus The modulus of the field the ECC curve is in + @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 *modulus, int map) +{ + ecc_point *tG, *M[8]; + int i, j, err; + void *mu, *mp; + unsigned long buf; + int first, bitbuf, bitcpy, bitcnt, mode, digidx; + + LTC_ARGCHK(k != NULL); + LTC_ARGCHK(G != NULL); + LTC_ARGCHK(R != NULL); + LTC_ARGCHK(modulus != NULL); + + /* init montgomery reduction */ + if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { + return err; + } + if ((err = mp_init(&mu)) != CRYPT_OK) { + mp_montgomery_free(mp); + return err; + } + if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { + mp_montgomery_free(mp); + mp_clear(mu); + return err; + } + + /* alloc ram for window temps */ + for (i = 0; i < 8; i++) { + M[i] = ltc_ecc_new_point(); + if (M[i] == NULL) { + for (j = 0; j < i; j++) { + ltc_ecc_del_point(M[j]); + } + mp_montgomery_free(mp); + mp_clear(mu); + return CRYPT_MEM; + } + } + + /* make a copy of G incase R==G */ + tG = ltc_ecc_new_point(); + if (tG == NULL) { err = CRYPT_MEM; goto done; } + + /* tG = G and convert to montgomery */ + if (mp_cmp_d(mu, 1) == LTC_MP_EQ) { + if ((err = mp_copy(G->x, tG->x)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(G->y, tG->y)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(G->z, tG->z)) != CRYPT_OK) { goto done; } + } else { + if ((err = mp_mulmod(G->x, mu, modulus, tG->x)) != CRYPT_OK) { goto done; } + if ((err = mp_mulmod(G->y, mu, modulus, tG->y)) != CRYPT_OK) { goto done; } + if ((err = mp_mulmod(G->z, mu, modulus, tG->z)) != CRYPT_OK) { goto done; } + } + mp_clear(mu); + mu = NULL; + + /* calc the M tab, which holds kG for k==8..15 */ + /* M[0] == 8G */ + if ((err = ltc_mp.ecc_ptdbl(tG, M[0], modulus, mp)) != CRYPT_OK) { goto done; } + if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], modulus, mp)) != CRYPT_OK) { goto done; } + if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], modulus, mp)) != CRYPT_OK) { goto done; } + + /* now find (8+k)G for k=1..7 */ + for (j = 9; j < 16; j++) { + if ((err = ltc_mp.ecc_ptadd(M[j-9], tG, M[j-8], modulus, mp)) != CRYPT_OK) { goto done; } + } + + /* setup sliding window */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = mp_get_digit_count(k) - 1; + bitcpy = bitbuf = 0; + first = 1; + + /* perform ops */ + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + if (digidx == -1) { + break; + } + buf = mp_get_digit(k, digidx); + bitcnt = (int) ltc_mp.bits_per_digit; + --digidx; + } + + /* grab the next msb from the ltiplicand */ + i = (buf >> (ltc_mp.bits_per_digit - 1)) & 1; + buf <<= 1; + + /* skip leading zero bits */ + if (mode == 0 && i == 0) { + continue; + } + + /* if the bit is zero and mode == 1 then we double */ + if (mode == 1 && i == 0) { + if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) { goto done; } + continue; + } + + /* else we add it to the window */ + bitbuf |= (i << (WINSIZE - ++bitcpy)); + mode = 2; + + if (bitcpy == WINSIZE) { + /* if this is the first window we do a simple copy */ + if (first == 1) { + /* R = kG [k = first window] */ + if ((err = mp_copy(M[bitbuf-8]->x, R->x)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(M[bitbuf-8]->y, R->y)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(M[bitbuf-8]->z, R->z)) != CRYPT_OK) { goto done; } + first = 0; + } else { + /* normal window */ + /* ok window is filled so double as required and add */ + /* double first */ + for (j = 0; j < WINSIZE; j++) { + if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) { goto done; } + } + + /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */ + if ((err = ltc_mp.ecc_ptadd(R, M[bitbuf-8], R, modulus, mp)) != CRYPT_OK) { goto done; } + } + /* empty window and reset */ + bitcpy = bitbuf = 0; + mode = 1; + } + } + + /* if bits remain then double/add */ + if (mode == 2 && bitcpy > 0) { + /* double then add */ + for (j = 0; j < bitcpy; j++) { + /* only double if we have had at least one add first */ + if (first == 0) { + if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) { goto done; } + } + + bitbuf <<= 1; + if ((bitbuf & (1 << WINSIZE)) != 0) { + if (first == 1){ + /* first add, so copy */ + if ((err = mp_copy(tG->x, R->x)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(tG->y, R->y)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(tG->z, R->z)) != CRYPT_OK) { goto done; } + first = 0; + } else { + /* then add */ + if ((err = ltc_mp.ecc_ptadd(R, tG, R, modulus, mp)) != CRYPT_OK) { goto done; } + } + } + } + } + + /* map R back from projective space */ + if (map) { + err = ltc_ecc_map(R, modulus, mp); + } else { + err = CRYPT_OK; + } +done: + if (mu != NULL) { + mp_clear(mu); + } + mp_montgomery_free(mp); + ltc_ecc_del_point(tG); + for (i = 0; i < 8; i++) { + ltc_ecc_del_point(M[i]); + } + return err; +} + +#else + +/* + * FUNCTION REWRITTEN BY Michael ADJEDJ + * due to the too high number of temp variables needed + * by the previous one. + */ + +/* size of sliding window, don't change this! MUST BE A POWER OF TWO */ +#define WINSIZE (2) +#define WINVARS (1 << (WINSIZE - 1)) + +/** + Perform a point multiplication + @param k The scalar to multiply by + @param G The base point + @param R [out] Destination for kG + @param modulus The modulus of the field the ECC curve is in + @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 *modulus, int map) +{ + ecc_point *tG, *M[WINVARS]; + int i, j, err; + void *mu, *mp; + unsigned long buf; + int first, bitbuf, bitcpy, bitcnt, mode, digidx; + + LTC_ARGCHK(k != NULL); + LTC_ARGCHK(G != NULL); + LTC_ARGCHK(R != NULL); + LTC_ARGCHK(modulus != NULL); + + /* init montgomery reduction */ + if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { + return err; + } + if ((err = mp_init(&mu)) != CRYPT_OK) { + mp_montgomery_free(mp); + return err; + } + if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { + mp_montgomery_free(mp); + mp_clear(mu); + return err; + } + + /* alloc ram for window temps */ + for (i = 0; i < WINVARS; i++) { + M[i] = ltc_ecc_new_point(); + if (M[i] == NULL) { + for (j = 0; j < i; j++) { + ltc_ecc_del_point(M[j]); + } + mp_montgomery_free(mp); + mp_clear(mu); + return CRYPT_MEM; + } + } + + tG = ltc_ecc_new_point(); + if (tG == NULL) { err = CRYPT_MEM; goto done; } + + /* tG = G and convert to montgomery */ + if (mp_cmp_d(mu, 1) == LTC_MP_EQ) { + if ((err = mp_copy(G->x, tG->x)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(G->y, tG->y)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(G->z, tG->z)) != CRYPT_OK) { goto done; } + } else { + if ((err = mp_mulmod(G->x, mu, modulus, tG->x)) != CRYPT_OK) { goto done; } + if ((err = mp_mulmod(G->y, mu, modulus, tG->y)) != CRYPT_OK) { goto done; } + if ((err = mp_mulmod(G->z, mu, modulus, tG->z)) != CRYPT_OK) { goto done; } + } + + + /* calc the M tab, which holds kG for k==8..15 */ + /* M[0] == [WINVARS].G */ + if ((err = ltc_mp.ecc_ptdbl(tG, M[0], modulus, mp)) != CRYPT_OK) { goto done; } + for (j = 1; j < (WINSIZE-1); ++j) { + if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], modulus, mp)) != CRYPT_OK) { goto done; } + } + + /* now find (WINVARS+k)G for k=1..(WINVARS-1) */ + for (j = (WINVARS + 1); j < (2*WINVARS); j++) { + if ((err = ltc_mp.ecc_ptadd(M[j-(WINVARS + 1)], tG, M[j-WINVARS], modulus, mp)) != CRYPT_OK) { goto done; } + } + + /* setup sliding window */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = mp_get_digit_count(k) - 1; + bitcpy = bitbuf = 0; + first = 1; + + /* perform ops */ + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + if (digidx == -1) { + break; + } + buf = mp_get_digit(k, digidx); + bitcnt = (int) ltc_mp.bits_per_digit; + --digidx; + } + + /* grab the next msb from the ltiplicand */ + i = (buf >> (ltc_mp.bits_per_digit - 1)) & 1; + buf <<= 1; + + /* skip leading zero bits */ + if (mode == 0 && i == 0) { + continue; + } + + /* if the bit is zero and mode == 1 then we double */ + if (mode == 1 && i == 0) { + if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) { goto done; } + continue; + } + + /* else we add it to the window */ + bitbuf |= (i << (WINSIZE - ++bitcpy)); + mode = 2; + + if (bitcpy == WINSIZE) { + /* if this is the first window we do a simple copy */ + if (first == 1) { + /* R = kG [k = first window] */ + if ((err = mp_copy(M[bitbuf-WINVARS]->x, R->x)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(M[bitbuf-WINVARS]->y, R->y)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(M[bitbuf-WINVARS]->z, R->z)) != CRYPT_OK) { goto done; } + first = 0; + } else { + /* normal window */ + /* ok window is filled so double as required and add */ + /* double first */ + for (j = 0; j < WINSIZE; j++) { + if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) { goto done; } + } + + /* then add, bitbuf will be WINVARS..(2*WINVARS - 1) guaranteed */ + if ((err = ltc_mp.ecc_ptadd(R, M[bitbuf-WINVARS], R, modulus, mp)) != CRYPT_OK) { goto done; } + } + /* empty window and reset */ + bitcpy = bitbuf = 0; + mode = 1; + } + } + + /* if bits remain then double/add */ + if (mode == 2 && bitcpy > 0) { + /* double then add */ + for (j = 0; j < bitcpy; j++) { + /* only double if we have had at least one add first */ + if (first == 0) { + if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) { goto done; } + } + + bitbuf <<= 1; + if ((bitbuf & (1 << WINSIZE)) != 0) { + if (first == 1){ + /* first add, so copy */ + if ((err = mp_copy(tG->x, R->x)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(tG->y, R->y)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(tG->z, R->z)) != CRYPT_OK) { goto done; } + first = 0; + } else { + /* then add */ + if ((err = ltc_mp.ecc_ptadd(R, tG, R, modulus, mp)) != CRYPT_OK) { goto done; } + } + } + } + } + + /* map R back from projective space */ + if (map) { + err = ltc_ecc_map(R, modulus, mp); + } else { + err = CRYPT_OK; + } + done: + + ltc_ecc_del_point(tG); + if (mu != NULL) { + mp_clear(mu); + } + mp_montgomery_free(mp); + for (i = 0; i < WINVARS; i++) { + ltc_ecc_del_point(M[i]); + } + return err; +} + + +#endif + +#endif + +#undef WINSIZE + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c,v $ */ +/* $Revision: 1.26 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c b/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c new file mode 100644 index 00000000000..3ac9173ff4d --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b + * + * All curves taken from NIST recommendation paper of July 1999 + * Available at http://csrc.nist.gov/cryptval/dss.htm + */ +#include "tomcrypt.h" + +/** + @file ltc_ecc_mulmod_timing.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +#ifdef LTC_ECC_TIMING_RESISTANT + +/** + Perform a point multiplication (timing resistant) + @param k The scalar to multiply by + @param G The base point + @param R [out] Destination for kG + @param modulus The modulus of the field the ECC curve is in + @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 *modulus, int map) +{ + ecc_point *tG, *M[3]; + int i, j, err; + void *mu, *mp; + unsigned long buf; + int first, bitbuf, bitcpy, bitcnt, mode, digidx; + + LTC_ARGCHK(k != NULL); + LTC_ARGCHK(G != NULL); + LTC_ARGCHK(R != NULL); + LTC_ARGCHK(modulus != NULL); + + /* init montgomery reduction */ + if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { + return err; + } + if ((err = mp_init(&mu)) != 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; + } + + /* alloc ram for window temps */ + for (i = 0; i < 3; i++) { + M[i] = ltc_ecc_new_point(); + if (M[i] == NULL) { + for (j = 0; j < i; j++) { + ltc_ecc_del_point(M[j]); + } + mp_clear(mu); + mp_montgomery_free(mp); + return CRYPT_MEM; + } + } + + /* make a copy of G incase R==G */ + tG = ltc_ecc_new_point(); + if (tG == NULL) { err = CRYPT_MEM; goto done; } + + /* tG = G and convert to montgomery */ + if ((err = mp_mulmod(G->x, mu, modulus, tG->x)) != CRYPT_OK) { goto done; } + if ((err = mp_mulmod(G->y, mu, modulus, tG->y)) != CRYPT_OK) { goto done; } + if ((err = mp_mulmod(G->z, mu, modulus, tG->z)) != CRYPT_OK) { goto done; } + mp_clear(mu); + mu = NULL; + + /* calc the M tab */ + /* M[0] == G */ + if ((err = mp_copy(tG->x, M[0]->x)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(tG->y, M[0]->y)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(tG->z, M[0]->z)) != CRYPT_OK) { goto done; } + /* M[1] == 2G */ + if ((err = ltc_mp.ecc_ptdbl(tG, M[1], modulus, mp)) != CRYPT_OK) { goto done; } + + /* setup sliding window */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = mp_get_digit_count(k) - 1; + bitcpy = bitbuf = 0; + first = 1; + + /* perform ops */ + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + if (digidx == -1) { + break; + } + buf = mp_get_digit(k, digidx); + bitcnt = (int) MP_DIGIT_BIT; + --digidx; + } + + /* grab the next msb from the ltiplicand */ + i = (buf >> (MP_DIGIT_BIT - 1)) & 1; + buf <<= 1; + + if (mode == 0 && i == 0) { + /* dummy operations */ + if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[2], modulus, mp)) != CRYPT_OK) { goto done; } + if ((err = ltc_mp.ecc_ptdbl(M[1], M[2], modulus, mp)) != CRYPT_OK) { goto done; } + continue; + } + + if (mode == 0 && i == 1) { + mode = 1; + /* dummy operations */ + if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[2], modulus, mp)) != CRYPT_OK) { goto done; } + if ((err = ltc_mp.ecc_ptdbl(M[1], M[2], modulus, mp)) != CRYPT_OK) { goto done; } + continue; + } + + if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[i^1], modulus, mp)) != CRYPT_OK) { goto done; } + if ((err = ltc_mp.ecc_ptdbl(M[i], M[i], modulus, mp)) != CRYPT_OK) { goto done; } + } + + /* copy result out */ + if ((err = mp_copy(M[0]->x, R->x)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(M[0]->y, R->y)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(M[0]->z, R->z)) != CRYPT_OK) { goto done; } + + /* map R back from projective space */ + if (map) { + err = ltc_ecc_map(R, modulus, mp); + } else { + err = CRYPT_OK; + } +done: + if (mu != NULL) { + mp_clear(mu); + } + mp_montgomery_free(mp); + ltc_ecc_del_point(tG); + for (i = 0; i < 3; i++) { + ltc_ecc_del_point(M[i]); + } + return err; +} + +#endif +#endif +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c,v $ */ +/* $Revision: 1.13 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_points.c b/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_points.c new file mode 100644 index 00000000000..b081fc31b93 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_points.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b + * + * All curves taken from NIST recommendation paper of July 1999 + * Available at http://csrc.nist.gov/cryptval/dss.htm + */ +#include "tomcrypt.h" + +/** + @file ltc_ecc_points.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** + Allocate a new ECC point + @return A newly allocated point or NULL on error +*/ +ecc_point *ltc_ecc_new_point(void) +{ + ecc_point *p; + p = XCALLOC(1, sizeof(*p)); + if (p == NULL) { + return NULL; + } + if (mp_init_multi(&p->x, &p->y, &p->z, NULL) != CRYPT_OK) { + XFREE(p); + return NULL; + } + return p; +} + +/** Free an ECC point from memory + @param p The point to free +*/ +void ltc_ecc_del_point(ecc_point *p) +{ + /* prevents free'ing null arguments */ + if (p != NULL) { + mp_clear_multi(p->x, p->y, p->z, NULL); /* note: p->z may be NULL but that's ok with this function anyways */ + XFREE(p); + } +} + +#endif +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_points.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c b/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c new file mode 100644 index 00000000000..2bcfd8f9963 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b + * + * All curves taken from NIST recommendation paper of July 1999 + * Available at http://csrc.nist.gov/cryptval/dss.htm + */ +#include "tomcrypt.h" + +/** + @file ltc_ecc_projective_add_point.c + ECC Crypto, Tom St Denis +*/ + +#if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_LTC_DESC)) + +/** + Add two ECC points + @param P The point to add + @param Q The point to add + @param R [out] The destination of the double + @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 *modulus, void *mp) +{ + void *t1, *t2, *x, *y, *z; + int err; + + LTC_ARGCHK(P != NULL); + LTC_ARGCHK(Q != NULL); + LTC_ARGCHK(R != NULL); + LTC_ARGCHK(modulus != NULL); + LTC_ARGCHK(mp != NULL); + + if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != CRYPT_OK) { + return err; + } + + /* should we dbl instead? */ + if ((err = mp_sub(modulus, Q->y, t1)) != CRYPT_OK) { goto done; } + + if ( (mp_cmp(P->x, Q->x) == LTC_MP_EQ) && + (Q->z != NULL && mp_cmp(P->z, Q->z) == LTC_MP_EQ) && + (mp_cmp(P->y, Q->y) == LTC_MP_EQ || mp_cmp(P->y, t1) == LTC_MP_EQ)) { + mp_clear_multi(t1, t2, x, y, z, NULL); + return ltc_ecc_projective_dbl_point(P, R, modulus, mp); + } + + if ((err = mp_copy(P->x, x)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(P->y, y)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(P->z, z)) != CRYPT_OK) { goto done; } + + /* if Z is one then these are no-operations */ + if (Q->z != NULL) { + /* T1 = Z' * Z' */ + if ((err = mp_sqr(Q->z, t1)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } + /* X = X * T1 */ + if ((err = mp_mul(t1, x, x)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; } + /* T1 = Z' * T1 */ + if ((err = mp_mul(Q->z, t1, t1)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } + /* Y = Y * T1 */ + if ((err = mp_mul(t1, y, y)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(y, modulus, mp)) != CRYPT_OK) { goto done; } + } + + /* T1 = Z*Z */ + if ((err = mp_sqr(z, t1)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } + /* T2 = X' * T1 */ + if ((err = mp_mul(Q->x, t1, t2)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } + /* T1 = Z * T1 */ + if ((err = mp_mul(z, t1, t1)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } + /* T1 = Y' * T1 */ + if ((err = mp_mul(Q->y, t1, t1)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } + + /* Y = Y - T1 */ + if ((err = mp_sub(y, t1, y)) != CRYPT_OK) { goto done; } + if (mp_cmp_d(y, 0) == LTC_MP_LT) { + if ((err = mp_add(y, modulus, y)) != CRYPT_OK) { goto done; } + } + /* T1 = 2T1 */ + if ((err = mp_add(t1, t1, t1)) != CRYPT_OK) { goto done; } + if (mp_cmp(t1, modulus) != LTC_MP_LT) { + if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } + } + /* T1 = Y + T1 */ + if ((err = mp_add(t1, y, t1)) != CRYPT_OK) { goto done; } + if (mp_cmp(t1, modulus) != LTC_MP_LT) { + if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } + } + /* X = X - T2 */ + if ((err = mp_sub(x, t2, x)) != CRYPT_OK) { goto done; } + if (mp_cmp_d(x, 0) == LTC_MP_LT) { + if ((err = mp_add(x, modulus, x)) != CRYPT_OK) { goto done; } + } + /* T2 = 2T2 */ + if ((err = mp_add(t2, t2, t2)) != CRYPT_OK) { goto done; } + if (mp_cmp(t2, modulus) != LTC_MP_LT) { + if ((err = mp_sub(t2, modulus, t2)) != CRYPT_OK) { goto done; } + } + /* T2 = X + T2 */ + if ((err = mp_add(t2, x, t2)) != CRYPT_OK) { goto done; } + if (mp_cmp(t2, modulus) != LTC_MP_LT) { + if ((err = mp_sub(t2, modulus, t2)) != CRYPT_OK) { goto done; } + } + + /* if Z' != 1 */ + if (Q->z != NULL) { + /* Z = Z * Z' */ + if ((err = mp_mul(z, Q->z, z)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(z, modulus, mp)) != CRYPT_OK) { goto done; } + } + + /* Z = Z * X */ + if ((err = mp_mul(z, x, z)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(z, modulus, mp)) != CRYPT_OK) { goto done; } + + /* T1 = T1 * X */ + if ((err = mp_mul(t1, x, t1)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } + /* X = X * X */ + if ((err = mp_sqr(x, x)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; } + /* T2 = T2 * x */ + if ((err = mp_mul(t2, x, t2)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } + /* T1 = T1 * X */ + if ((err = mp_mul(t1, x, t1)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } + + /* X = Y*Y */ + if ((err = mp_sqr(y, x)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; } + /* X = X - T2 */ + if ((err = mp_sub(x, t2, x)) != CRYPT_OK) { goto done; } + if (mp_cmp_d(x, 0) == LTC_MP_LT) { + if ((err = mp_add(x, modulus, x)) != CRYPT_OK) { goto done; } + } + + /* T2 = T2 - X */ + if ((err = mp_sub(t2, x, t2)) != CRYPT_OK) { goto done; } + if (mp_cmp_d(t2, 0) == LTC_MP_LT) { + if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; } + } + /* T2 = T2 - X */ + if ((err = mp_sub(t2, x, t2)) != CRYPT_OK) { goto done; } + if (mp_cmp_d(t2, 0) == LTC_MP_LT) { + if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; } + } + /* T2 = T2 * Y */ + if ((err = mp_mul(t2, y, t2)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } + /* Y = T2 - T1 */ + if ((err = mp_sub(t2, t1, y)) != CRYPT_OK) { goto done; } + if (mp_cmp_d(y, 0) == LTC_MP_LT) { + if ((err = mp_add(y, modulus, y)) != CRYPT_OK) { goto done; } + } + /* Y = Y/2 */ + if (mp_isodd(y)) { + if ((err = mp_add(y, modulus, y)) != CRYPT_OK) { goto done; } + } + if ((err = mp_div_2(y, y)) != CRYPT_OK) { goto done; } + + if ((err = mp_copy(x, R->x)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(y, R->y)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(z, R->z)) != CRYPT_OK) { goto done; } + + err = CRYPT_OK; +done: + mp_clear_multi(t1, t2, x, y, z, NULL); + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c,v $ */ +/* $Revision: 1.16 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c b/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c new file mode 100644 index 00000000000..a1bde19e9e7 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b + * + * All curves taken from NIST recommendation paper of July 1999 + * Available at http://csrc.nist.gov/cryptval/dss.htm + */ +#include "tomcrypt.h" + +/** + @file ltc_ecc_projective_dbl_point.c + ECC Crypto, Tom St Denis +*/ + +#if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_LTC_DESC)) + +/** + Double an ECC point + @param P The point to double + @param R [out] The destination of the double + @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 *modulus, void *mp) +{ + void *t1, *t2; + int err; + + LTC_ARGCHK(P != NULL); + LTC_ARGCHK(R != NULL); + LTC_ARGCHK(modulus != NULL); + LTC_ARGCHK(mp != NULL); + + if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) { + return err; + } + + if (P != R) { + if ((err = mp_copy(P->x, R->x)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(P->y, R->y)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(P->z, R->z)) != CRYPT_OK) { goto done; } + } + + /* t1 = Z * Z */ + if ((err = mp_sqr(R->z, t1)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } + /* Z = Y * Z */ + if ((err = mp_mul(R->z, R->y, R->z)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(R->z, modulus, mp)) != CRYPT_OK) { goto done; } + /* Z = 2Z */ + if ((err = mp_add(R->z, R->z, R->z)) != CRYPT_OK) { goto done; } + if (mp_cmp(R->z, modulus) != LTC_MP_LT) { + if ((err = mp_sub(R->z, modulus, R->z)) != CRYPT_OK) { goto done; } + } + + /* T2 = X - T1 */ + if ((err = mp_sub(R->x, t1, t2)) != CRYPT_OK) { goto done; } + if (mp_cmp_d(t2, 0) == LTC_MP_LT) { + if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; } + } + /* T1 = X + T1 */ + if ((err = mp_add(t1, R->x, t1)) != CRYPT_OK) { goto done; } + if (mp_cmp(t1, modulus) != LTC_MP_LT) { + if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } + } + /* T2 = T1 * T2 */ + if ((err = mp_mul(t1, t2, t2)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } + /* T1 = 2T2 */ + if ((err = mp_add(t2, t2, t1)) != CRYPT_OK) { goto done; } + if (mp_cmp(t1, modulus) != LTC_MP_LT) { + if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } + } + /* T1 = T1 + T2 */ + if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; } + if (mp_cmp(t1, modulus) != LTC_MP_LT) { + if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } + } + + /* Y = 2Y */ + if ((err = mp_add(R->y, R->y, R->y)) != CRYPT_OK) { goto done; } + if (mp_cmp(R->y, modulus) != LTC_MP_LT) { + if ((err = mp_sub(R->y, modulus, R->y)) != CRYPT_OK) { goto done; } + } + /* Y = Y * Y */ + if ((err = mp_sqr(R->y, R->y)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK) { goto done; } + /* T2 = Y * Y */ + if ((err = mp_sqr(R->y, t2)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } + /* T2 = T2/2 */ + if (mp_isodd(t2)) { + if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; } + } + if ((err = mp_div_2(t2, t2)) != CRYPT_OK) { goto done; } + /* Y = Y * X */ + if ((err = mp_mul(R->y, R->x, R->y)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK) { goto done; } + + /* X = T1 * T1 */ + if ((err = mp_sqr(t1, R->x)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(R->x, modulus, mp)) != CRYPT_OK) { goto done; } + /* X = X - Y */ + if ((err = mp_sub(R->x, R->y, R->x)) != CRYPT_OK) { goto done; } + if (mp_cmp_d(R->x, 0) == LTC_MP_LT) { + if ((err = mp_add(R->x, modulus, R->x)) != CRYPT_OK) { goto done; } + } + /* X = X - Y */ + if ((err = mp_sub(R->x, R->y, R->x)) != CRYPT_OK) { goto done; } + if (mp_cmp_d(R->x, 0) == LTC_MP_LT) { + if ((err = mp_add(R->x, modulus, R->x)) != CRYPT_OK) { goto done; } + } + + /* Y = Y - X */ + if ((err = mp_sub(R->y, R->x, R->y)) != CRYPT_OK) { goto done; } + if (mp_cmp_d(R->y, 0) == LTC_MP_LT) { + if ((err = mp_add(R->y, modulus, R->y)) != CRYPT_OK) { goto done; } + } + /* Y = Y * T1 */ + if ((err = mp_mul(R->y, t1, R->y)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK) { goto done; } + /* Y = Y - T2 */ + if ((err = mp_sub(R->y, t2, R->y)) != CRYPT_OK) { goto done; } + if (mp_cmp_d(R->y, 0) == LTC_MP_LT) { + if ((err = mp_add(R->y, modulus, R->y)) != CRYPT_OK) { goto done; } + } + + err = CRYPT_OK; +done: + mp_clear_multi(t1, t2, NULL); + return err; +} +#endif +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c,v $ */ +/* $Revision: 1.11 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/ecc/sub.mk b/core/lib/libtomcrypt/src/pk/ecc/sub.mk new file mode 100644 index 00000000000..8edd3f6e55e --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/ecc/sub.mk @@ -0,0 +1,23 @@ +srcs-y += ecc_ansi_x963_export.c +srcs-y += ecc_ansi_x963_import.c +srcs-y += ecc.c +srcs-y += ecc_decrypt_key.c +srcs-y += ecc_encrypt_key.c +srcs-y += ecc_export.c +srcs-y += ecc_free.c +srcs-y += ecc_get_size.c +srcs-y += ecc_import.c +srcs-y += ecc_make_key.c +srcs-y += ecc_shared_secret.c +srcs-y += ecc_sign_hash.c +srcs-y += ecc_sizes.c +srcs-y += ecc_test.c +srcs-y += ecc_verify_hash.c +srcs-y += ltc_ecc_is_valid_idx.c +srcs-y += ltc_ecc_map.c +srcs-y += ltc_ecc_mul2add.c +srcs-y += ltc_ecc_mulmod.c +srcs-y += ltc_ecc_mulmod_timing.c +srcs-y += ltc_ecc_points.c +srcs-y += ltc_ecc_projective_add_point.c +srcs-y += ltc_ecc_projective_dbl_point.c diff --git a/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c b/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c new file mode 100644 index 00000000000..5e40bcb7b4a --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file pkcs_1_i2osp.c + Integer to Octet I2OSP, Tom St Denis +*/ + +#ifdef LTC_PKCS_1 + +/* always stores the same # of bytes, pads with leading zero bytes + as required + */ + +/** + LTC_PKCS #1 Integer to binary + @param n The integer to store + @param modulus_len The length of the RSA modulus + @param out [out] The destination for the integer + @return CRYPT_OK if successful +*/ +int pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out) +{ + unsigned long size; + + size = mp_unsigned_bin_size(n); + + if (size > modulus_len) { + return CRYPT_BUFFER_OVERFLOW; + } + + /* store it */ + zeromem(out, modulus_len); + return mp_to_unsigned_bin(n, out+(modulus_len-size)); +} + +#endif /* LTC_PKCS_1 */ + + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c b/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c new file mode 100644 index 00000000000..f8c5cc2777f --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file pkcs_1_mgf1.c + The Mask Generation Function (MGF1) for LTC_PKCS #1, Tom St Denis +*/ + +#ifdef LTC_PKCS_1 + +/** + Perform LTC_PKCS #1 MGF1 (internal) + @param seed The seed for MGF1 + @param seedlen The length of the seed + @param hash_idx The index of the hash desired + @param mask [out] The destination + @param masklen The length of the mask desired + @return CRYPT_OK if successful +*/ +int pkcs_1_mgf1(int hash_idx, + const unsigned char *seed, unsigned long seedlen, + unsigned char *mask, unsigned long masklen) +{ + unsigned long hLen, x; + ulong32 counter; + int err; + hash_state *md; + unsigned char *buf; + + LTC_ARGCHK(seed != NULL); + LTC_ARGCHK(mask != NULL); + + /* ensure valid hash */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + + /* get hash output size */ + hLen = hash_descriptor[hash_idx].hashsize; + + /* allocate memory */ + md = XMALLOC(sizeof(hash_state)); + buf = XMALLOC(hLen); + if (md == NULL || buf == NULL) { + if (md != NULL) { + XFREE(md); + } + if (buf != NULL) { + XFREE(buf); + } + return CRYPT_MEM; + } + + /* start counter */ + counter = 0; + + while (masklen > 0) { + /* handle counter */ + STORE32H(counter, buf); + ++counter; + + /* get hash of seed || counter */ + if ((err = hash_descriptor[hash_idx].init(md)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash_idx].process(md, seed, seedlen)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash_idx].process(md, buf, 4)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash_idx].done(md, buf)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* store it */ + for (x = 0; x < hLen && masklen > 0; x++, masklen--) { + *mask++ = buf[x]; + } + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(buf, hLen); + zeromem(md, sizeof(hash_state)); +#endif + + XFREE(buf); + XFREE(md); + + return err; +} + +#endif /* LTC_PKCS_1 */ + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c b/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c new file mode 100644 index 00000000000..db6f0ef3739 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file pkcs_1_oaep_decode.c + OAEP Padding for LTC_PKCS #1, Tom St Denis +*/ + +#ifdef LTC_PKCS_1 + +/** + LTC_PKCS #1 v2.00 OAEP decode + @param msg The encoded data to decode + @param msglen The length of the encoded data (octets) + @param lparam The session or system data (can be NULL) + @param lparamlen The length of the lparam + @param modulus_bitlen The bit length of the RSA modulus + @param hash_idx The index of the hash desired + @param out [out] Destination of decoding + @param outlen [in/out] The max size and resulting size of the decoding + @param res [out] Result of decoding, 1==valid, 0==invalid + @return CRYPT_OK if successful (even if invalid) +*/ +int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, + const unsigned char *lparam, unsigned long lparamlen, + unsigned long modulus_bitlen, int hash_idx, + unsigned char *out, unsigned long *outlen, + int *res) +{ + unsigned char *DB, *seed, *mask; + unsigned long hLen, x, y, modulus_len; + int err; + + LTC_ARGCHK(msg != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(res != NULL); + + /* default to invalid packet */ + *res = 0; + + /* test valid hash */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + hLen = hash_descriptor[hash_idx].hashsize; + modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); + + /* test hash/message size */ + if ((2*hLen >= (modulus_len - 2)) || (msglen != modulus_len)) { + return CRYPT_PK_INVALID_SIZE; + } + + /* allocate ram for DB/mask/salt of size modulus_len */ + DB = XMALLOC(modulus_len); + mask = XMALLOC(modulus_len); + seed = XMALLOC(hLen); + if (DB == NULL || mask == NULL || seed == NULL) { + if (DB != NULL) { + XFREE(DB); + } + if (mask != NULL) { + XFREE(mask); + } + if (seed != NULL) { + XFREE(seed); + } + return CRYPT_MEM; + } + + /* ok so it's now in the form + + 0x00 || maskedseed || maskedDB + + 1 || hLen || modulus_len - hLen - 1 + + */ + + /* must have leading 0x00 byte */ + if (msg[0] != 0x00) { + err = CRYPT_OK; + goto LBL_ERR; + } + + /* now read the masked seed */ + x = 1; + XMEMCPY(seed, msg + x, hLen); + x += hLen; + + /* now read the masked DB */ + XMEMCPY(DB, msg + x, modulus_len - hLen - 1); + x += modulus_len - hLen - 1; + + /* compute MGF1 of maskedDB (hLen) */ + if ((err = pkcs_1_mgf1(hash_idx, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* XOR against seed */ + for (y = 0; y < hLen; y++) { + seed[y] ^= mask[y]; + } + + /* compute MGF1 of seed (k - hlen - 1) */ + if ((err = pkcs_1_mgf1(hash_idx, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* xor against DB */ + for (y = 0; y < (modulus_len - hLen - 1); y++) { + DB[y] ^= mask[y]; + } + + /* now DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */ + + /* compute lhash and store it in seed [reuse temps!] */ + x = modulus_len; + if (lparam != NULL) { + if ((err = hash_memory(hash_idx, lparam, lparamlen, seed, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + } else { + /* can't pass hash_memory a NULL so use DB with zero length */ + if ((err = hash_memory(hash_idx, DB, 0, seed, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + } + + /* compare the lhash'es */ + if (XMEMCMP(seed, DB, hLen) != 0) { + err = CRYPT_OK; + goto LBL_ERR; + } + + /* now zeroes before a 0x01 */ + for (x = hLen; x < (modulus_len - hLen - 1) && DB[x] == 0x00; x++) { + /* step... */ + } + + /* error out if wasn't 0x01 */ + if (x == (modulus_len - hLen - 1) || DB[x] != 0x01) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + /* rest is the message (and skip 0x01) */ + if ((modulus_len - hLen - 1 - ++x) > *outlen) { + *outlen = modulus_len - hLen - 1 - x; + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + + /* copy message */ + *outlen = modulus_len - hLen - 1 - x; + XMEMCPY(out, DB + x, modulus_len - hLen - 1 - x); + x += modulus_len - hLen - 1; + + /* valid packet */ + *res = 1; + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(DB, modulus_len); + zeromem(seed, hLen); + zeromem(mask, modulus_len); +#endif + + XFREE(seed); + XFREE(mask); + XFREE(DB); + + return err; +} + +#endif /* LTC_PKCS_1 */ + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c,v $ */ +/* $Revision: 1.13 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c b/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c new file mode 100644 index 00000000000..e52a073abf2 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file pkcs_1_oaep_encode.c + OAEP Padding for LTC_PKCS #1, Tom St Denis +*/ + +#ifdef LTC_PKCS_1 + +/** + LTC_PKCS #1 v2.00 OAEP encode + @param msg The data to encode + @param msglen The length of the data to encode (octets) + @param lparam A session or system parameter (can be NULL) + @param lparamlen The length of the lparam data + @param modulus_bitlen The bit length of the RSA modulus + @param prng An active PRNG state + @param prng_idx The index of the PRNG desired + @param hash_idx The index of the hash desired + @param out [out] The destination for the encoded data + @param outlen [in/out] The max size and resulting size of the encoded data + @return CRYPT_OK if successful +*/ +int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, + const unsigned char *lparam, unsigned long lparamlen, + unsigned long modulus_bitlen, prng_state *prng, + int prng_idx, int hash_idx, + unsigned char *out, unsigned long *outlen) +{ + unsigned char *DB, *seed, *mask; + unsigned long hLen, x, y, modulus_len; + int err; + + LTC_ARGCHK(msg != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* test valid hash */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + + /* valid prng */ + if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { + return err; + } + + hLen = hash_descriptor[hash_idx].hashsize; + modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); + + /* test message size */ + if ((2*hLen >= (modulus_len - 2)) || (msglen > (modulus_len - 2*hLen - 2))) { + return CRYPT_PK_INVALID_SIZE; + } + + /* allocate ram for DB/mask/salt of size modulus_len */ + DB = XMALLOC(modulus_len); + mask = XMALLOC(modulus_len); + seed = XMALLOC(hLen); + if (DB == NULL || mask == NULL || seed == NULL) { + if (DB != NULL) { + XFREE(DB); + } + if (mask != NULL) { + XFREE(mask); + } + if (seed != NULL) { + XFREE(seed); + } + return CRYPT_MEM; + } + + /* get lhash */ + /* DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */ + x = modulus_len; + if (lparam != NULL) { + if ((err = hash_memory(hash_idx, lparam, lparamlen, DB, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + } else { + /* can't pass hash_memory a NULL so use DB with zero length */ + if ((err = hash_memory(hash_idx, DB, 0, DB, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + } + + /* append PS then 0x01 (to lhash) */ + x = hLen; + y = modulus_len - msglen - 2*hLen - 2; + XMEMSET(DB+x, 0, y); + x += y; + + /* 0x01 byte */ + DB[x++] = 0x01; + + /* message (length = msglen) */ + XMEMCPY(DB+x, msg, msglen); + x += msglen; + + /* now choose a random seed */ + if (prng_descriptor[prng_idx].read(seed, hLen, prng) != hLen) { + err = CRYPT_ERROR_READPRNG; + goto LBL_ERR; + } + + /* compute MGF1 of seed (k - hlen - 1) */ + if ((err = pkcs_1_mgf1(hash_idx, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* xor against DB */ + for (y = 0; y < (modulus_len - hLen - 1); y++) { + DB[y] ^= mask[y]; + } + + /* compute MGF1 of maskedDB (hLen) */ + if ((err = pkcs_1_mgf1(hash_idx, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* XOR against seed */ + for (y = 0; y < hLen; y++) { + seed[y] ^= mask[y]; + } + + /* create string of length modulus_len */ + if (*outlen < modulus_len) { + *outlen = modulus_len; + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + + /* start output which is 0x00 || maskedSeed || maskedDB */ + x = 0; + out[x++] = 0x00; + XMEMCPY(out+x, seed, hLen); + x += hLen; + XMEMCPY(out+x, DB, modulus_len - hLen - 1); + x += modulus_len - hLen - 1; + + *outlen = x; + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(DB, modulus_len); + zeromem(seed, hLen); + zeromem(mask, modulus_len); +#endif + + XFREE(seed); + XFREE(mask); + XFREE(DB); + + return err; +} + +#endif /* LTC_PKCS_1 */ + + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c,v $ */ +/* $Revision: 1.9 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c b/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c new file mode 100644 index 00000000000..ee4d9475763 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file pkcs_1_os2ip.c + Octet to Integer OS2IP, Tom St Denis +*/ +#ifdef LTC_PKCS_1 + +/** + Read a binary string into an mp_int + @param n [out] The mp_int destination + @param in The binary string to read + @param inlen The length of the binary string + @return CRYPT_OK if successful +*/ +int pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen) +{ + return mp_read_unsigned_bin(n, in, inlen); +} + +#endif /* LTC_PKCS_1 */ + + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c b/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c new file mode 100644 index 00000000000..a9fa7c90566 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file pkcs_1_pss_decode.c + LTC_PKCS #1 PSS Signature Padding, Tom St Denis +*/ + +#ifdef LTC_PKCS_1 + +/** + LTC_PKCS #1 v2.00 PSS decode + @param msghash The hash to verify + @param msghashlen The length of the hash (octets) + @param sig The signature data (encoded data) + @param siglen The length of the signature data (octets) + @param saltlen The length of the salt used (octets) + @param hash_idx The index of the hash desired + @param modulus_bitlen The bit length of the RSA modulus + @param res [out] The result of the comparison, 1==valid, 0==invalid + @return CRYPT_OK if successful (even if the comparison failed) +*/ +int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, + const unsigned char *sig, unsigned long siglen, + unsigned long saltlen, int hash_idx, + unsigned long modulus_bitlen, int *res) +{ + unsigned char *DB, *mask, *salt, *hash; + unsigned long x, y, hLen, modulus_len; + int err; + hash_state md; + + LTC_ARGCHK(msghash != NULL); + LTC_ARGCHK(res != NULL); + + /* default to invalid */ + *res = 0; + + /* ensure hash is valid */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + + hLen = hash_descriptor[hash_idx].hashsize; + modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); + + /* check sizes */ + if ((saltlen > modulus_len) || + (modulus_len < hLen + saltlen + 2) || (siglen != modulus_len)) { + return CRYPT_PK_INVALID_SIZE; + } + + /* allocate ram for DB/mask/salt/hash of size modulus_len */ + DB = XMALLOC(modulus_len); + mask = XMALLOC(modulus_len); + salt = XMALLOC(modulus_len); + hash = XMALLOC(modulus_len); + if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) { + if (DB != NULL) { + XFREE(DB); + } + if (mask != NULL) { + XFREE(mask); + } + if (salt != NULL) { + XFREE(salt); + } + if (hash != NULL) { + XFREE(hash); + } + return CRYPT_MEM; + } + + /* ensure the 0xBC byte */ + if (sig[siglen-1] != 0xBC) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + /* copy out the DB */ + x = 0; + XMEMCPY(DB, sig + x, modulus_len - hLen - 1); + x += modulus_len - hLen - 1; + + /* copy out the hash */ + XMEMCPY(hash, sig + x, hLen); + x += hLen; + + /* check the MSB */ + if ((sig[0] & ~(0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)))) != 0) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + /* generate mask of length modulus_len - hLen - 1 from hash */ + if ((err = pkcs_1_mgf1(hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* xor against DB */ + for (y = 0; y < (modulus_len - hLen - 1); y++) { + DB[y] ^= mask[y]; + } + + /* now clear the first byte [make sure smaller than modulus] */ + DB[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)); + + /* DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */ + + /* check for zeroes and 0x01 */ + for (x = 0; x < modulus_len - saltlen - hLen - 2; x++) { + if (DB[x] != 0x00) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + } + + /* check for the 0x01 */ + if (DB[x++] != 0x01) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + /* M = (eight) 0x00 || msghash || salt, mask = H(M) */ + if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) { + goto LBL_ERR; + } + zeromem(mask, 8); + if ((err = hash_descriptor[hash_idx].process(&md, mask, 8)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash_idx].process(&md, DB+x, saltlen)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash_idx].done(&md, mask)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* mask == hash means valid signature */ + if (XMEMCMP(mask, hash, hLen) == 0) { + *res = 1; + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(DB, modulus_len); + zeromem(mask, modulus_len); + zeromem(salt, modulus_len); + zeromem(hash, modulus_len); +#endif + + XFREE(hash); + XFREE(salt); + XFREE(mask); + XFREE(DB); + + return err; +} + +#endif /* LTC_PKCS_1 */ + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c,v $ */ +/* $Revision: 1.11 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c b/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c new file mode 100644 index 00000000000..14766bd7cb6 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file pkcs_1_pss_encode.c + LTC_PKCS #1 PSS Signature Padding, Tom St Denis +*/ + +#ifdef LTC_PKCS_1 + +/** + LTC_PKCS #1 v2.00 Signature Encoding + @param msghash The hash to encode + @param msghashlen The length of the hash (octets) + @param saltlen The length of the salt desired (octets) + @param prng An active PRNG context + @param prng_idx The index of the PRNG desired + @param hash_idx The index of the hash desired + @param modulus_bitlen The bit length of the RSA modulus + @param out [out] The destination of the encoding + @param outlen [in/out] The max size and resulting size of the encoded data + @return CRYPT_OK if successful +*/ +int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, + unsigned long saltlen, prng_state *prng, + int prng_idx, int hash_idx, + unsigned long modulus_bitlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned char *DB, *mask, *salt, *hash; + unsigned long x, y, hLen, modulus_len; + int err; + hash_state md; + + LTC_ARGCHK(msghash != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* ensure hash and PRNG are valid */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { + return err; + } + + hLen = hash_descriptor[hash_idx].hashsize; + modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); + + /* check sizes */ + if ((saltlen > modulus_len) || (modulus_len < hLen + saltlen + 2)) { + return CRYPT_PK_INVALID_SIZE; + } + + /* allocate ram for DB/mask/salt/hash of size modulus_len */ + DB = XMALLOC(modulus_len); + mask = XMALLOC(modulus_len); + salt = XMALLOC(modulus_len); + hash = XMALLOC(modulus_len); + if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) { + if (DB != NULL) { + XFREE(DB); + } + if (mask != NULL) { + XFREE(mask); + } + if (salt != NULL) { + XFREE(salt); + } + if (hash != NULL) { + XFREE(hash); + } + return CRYPT_MEM; + } + + + /* generate random salt */ + if (saltlen > 0) { + if (prng_descriptor[prng_idx].read(salt, saltlen, prng) != saltlen) { + err = CRYPT_ERROR_READPRNG; + goto LBL_ERR; + } + } + + /* M = (eight) 0x00 || msghash || salt, hash = H(M) */ + if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) { + goto LBL_ERR; + } + zeromem(DB, 8); + if ((err = hash_descriptor[hash_idx].process(&md, DB, 8)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash_idx].process(&md, salt, saltlen)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash_idx].done(&md, hash)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* generate DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */ + x = 0; + XMEMSET(DB + x, 0, modulus_len - saltlen - hLen - 2); + x += modulus_len - saltlen - hLen - 2; + DB[x++] = 0x01; + XMEMCPY(DB + x, salt, saltlen); + x += saltlen; + + /* generate mask of length modulus_len - hLen - 1 from hash */ + if ((err = pkcs_1_mgf1(hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* xor against DB */ + for (y = 0; y < (modulus_len - hLen - 1); y++) { + DB[y] ^= mask[y]; + } + + /* output is DB || hash || 0xBC */ + if (*outlen < modulus_len) { + *outlen = modulus_len; + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + + /* DB len = modulus_len - hLen - 1 */ + y = 0; + XMEMCPY(out + y, DB, modulus_len - hLen - 1); + y += modulus_len - hLen - 1; + + /* hash */ + XMEMCPY(out + y, hash, hLen); + y += hLen; + + /* 0xBC */ + out[y] = 0xBC; + + /* now clear the 8*modulus_len - modulus_bitlen most significant bits */ + out[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)); + + /* store output size */ + *outlen = modulus_len; + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(DB, modulus_len); + zeromem(mask, modulus_len); + zeromem(salt, modulus_len); + zeromem(hash, modulus_len); +#endif + + XFREE(hash); + XFREE(salt); + XFREE(mask); + XFREE(DB); + + return err; +} + +#endif /* LTC_PKCS_1 */ + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c,v $ */ +/* $Revision: 1.9 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c b/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c new file mode 100644 index 00000000000..d250046c6ef --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** @file pkcs_1_v1_5_decode.c + * + * LTC_PKCS #1 v1.5 Padding. (Andreas Lange) + */ + +#ifdef LTC_PKCS_1 + +/** @brief LTC_PKCS #1 v1.5 decode. + * + * @param msg The encoded data to decode + * @param msglen The length of the encoded data (octets) + * @param block_type Block type to use in padding (\sa ltc_pkcs_1_v1_5_blocks) + * @param modulus_bitlen The bit length of the RSA modulus + * @param out [out] Destination of decoding + * @param outlen [in/out] The max size and resulting size of the decoding + * @param is_valid [out] Boolean whether the padding was valid + * + * @return CRYPT_OK if successful (even if invalid) + */ +int pkcs_1_v1_5_decode(const unsigned char *msg, + unsigned long msglen, + int block_type, + unsigned long modulus_bitlen, + unsigned char *out, + unsigned long *outlen, + int *is_valid) +{ + unsigned long modulus_len, ps_len, i; + int result; + + /* default to invalid packet */ + *is_valid = 0; + + modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); + + /* test message size */ + + if ((msglen > modulus_len) || (modulus_len < 11)) { + return CRYPT_PK_INVALID_SIZE; + } + + /* separate encoded message */ + + if ((msg[0] != 0x00) || (msg[1] != (unsigned char)block_type)) { + result = CRYPT_INVALID_PACKET; + goto bail; + } + + if (block_type == LTC_LTC_PKCS_1_EME) { + for (i = 2; i < modulus_len; i++) { + /* separator */ + if (msg[i] == 0x00) { break; } + } + ps_len = i++ - 2; + + if ((i >= modulus_len) || (ps_len < 8)) { + /* There was no octet with hexadecimal value 0x00 to separate ps from m, + * or the length of ps is less than 8 octets. + */ + result = CRYPT_INVALID_PACKET; + goto bail; + } + } else { + for (i = 2; i < modulus_len - 1; i++) { + if (msg[i] != 0xFF) { break; } + } + + /* separator check */ + if (msg[i] != 0) { + /* There was no octet with hexadecimal value 0x00 to separate ps from m. */ + result = CRYPT_INVALID_PACKET; + goto bail; + } + + ps_len = i - 2; + } + + if (*outlen < (msglen - (2 + ps_len + 1))) { + *outlen = msglen - (2 + ps_len + 1); + result = CRYPT_BUFFER_OVERFLOW; + goto bail; + } + + *outlen = (msglen - (2 + ps_len + 1)); + XMEMCPY(out, &msg[2 + ps_len + 1], *outlen); + + /* valid packet */ + *is_valid = 1; + result = CRYPT_OK; +bail: + return result; +} /* pkcs_1_v1_5_decode */ + +#endif /* #ifdef LTC_PKCS_1 */ + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c b/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c new file mode 100644 index 00000000000..f58f990cbb9 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/*! \file pkcs_1_v1_5_encode.c + * + * LTC_PKCS #1 v1.5 Padding (Andreas Lange) + */ + +#ifdef LTC_PKCS_1 + +/*! \brief LTC_PKCS #1 v1.5 encode. + * + * \param msg The data to encode + * \param msglen The length of the data to encode (octets) + * \param block_type Block type to use in padding (\sa ltc_pkcs_1_v1_5_blocks) + * \param modulus_bitlen The bit length of the RSA modulus + * \param prng An active PRNG state (only for LTC_LTC_PKCS_1_EME) + * \param prng_idx The index of the PRNG desired (only for LTC_LTC_PKCS_1_EME) + * \param out [out] The destination for the encoded data + * \param outlen [in/out] The max size and resulting size of the encoded data + * + * \return CRYPT_OK if successful + */ +int pkcs_1_v1_5_encode(const unsigned char *msg, + unsigned long msglen, + int block_type, + unsigned long modulus_bitlen, + prng_state *prng, + int prng_idx, + unsigned char *out, + unsigned long *outlen) +{ + unsigned long modulus_len, ps_len, i; + unsigned char *ps; + int result; + + /* valid block_type? */ + if ((block_type != LTC_LTC_PKCS_1_EMSA) && + (block_type != LTC_LTC_PKCS_1_EME)) { + return CRYPT_PK_INVALID_PADDING; + } + + if (block_type == LTC_LTC_PKCS_1_EME) { /* encryption padding, we need a valid PRNG */ + if ((result = prng_is_valid(prng_idx)) != CRYPT_OK) { + return result; + } + } + + modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); + + /* test message size */ + if ((msglen + 11) > modulus_len) { + return CRYPT_PK_INVALID_SIZE; + } + + if (*outlen < modulus_len) { + *outlen = modulus_len; + result = CRYPT_BUFFER_OVERFLOW; + goto bail; + } + + /* generate an octets string PS */ + ps = &out[2]; + ps_len = modulus_len - msglen - 3; + + if (block_type == LTC_LTC_PKCS_1_EME) { + /* now choose a random ps */ + if (prng_descriptor[prng_idx].read(ps, ps_len, prng) != ps_len) { + result = CRYPT_ERROR_READPRNG; + goto bail; + } + + /* transform zero bytes (if any) to non-zero random bytes */ + for (i = 0; i < ps_len; i++) { + while (ps[i] == 0) { + if (prng_descriptor[prng_idx].read(&ps[i], 1, prng) != 1) { + result = CRYPT_ERROR_READPRNG; + goto bail; + } + } + } + } else { + XMEMSET(ps, 0xFF, ps_len); + } + + /* create string of length modulus_len */ + out[0] = 0x00; + out[1] = (unsigned char)block_type; /* block_type 1 or 2 */ + out[2 + ps_len] = 0x00; + XMEMCPY(&out[2 + ps_len + 1], msg, msglen); + *outlen = modulus_len; + + result = CRYPT_OK; +bail: + return result; +} /* pkcs_1_v1_5_encode */ + +#endif /* #ifdef LTC_PKCS_1 */ + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/pkcs1/sub.mk b/core/lib/libtomcrypt/src/pk/pkcs1/sub.mk new file mode 100644 index 00000000000..43f96b96e94 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/pkcs1/sub.mk @@ -0,0 +1,9 @@ +srcs-y += pkcs_1_i2osp.c +srcs-y += pkcs_1_mgf1.c +srcs-y += pkcs_1_oaep_decode.c +srcs-y += pkcs_1_oaep_encode.c +srcs-y += pkcs_1_os2ip.c +srcs-y += pkcs_1_pss_decode.c +srcs-y += pkcs_1_pss_encode.c +srcs-y += pkcs_1_v1_5_decode.c +srcs-y += pkcs_1_v1_5_encode.c diff --git a/core/lib/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c b/core/lib/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c new file mode 100644 index 00000000000..43f2b1397f1 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file rsa_decrypt_key.c + RSA LTC_PKCS #1 Decryption, Tom St Denis and Andreas Lange +*/ + +#ifdef LTC_MRSA + +/** + LTC_PKCS #1 decrypt then v1.5 or OAEP depad + @param in The ciphertext + @param inlen The length of the ciphertext (octets) + @param out [out] The plaintext + @param outlen [in/out] The max size and resulting size of the plaintext (octets) + @param lparam The system "lparam" value + @param lparamlen The length of the lparam value (octets) + @param hash_idx The index of the hash desired + @param padding Type of padding (LTC_LTC_PKCS_1_OAEP or LTC_LTC_PKCS_1_V1_5) + @param stat [out] Result of the decryption, 1==valid, 0==invalid + @param key The corresponding private RSA key + @return CRYPT_OK if succcessul (even if invalid) +*/ +int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const unsigned char *lparam, unsigned long lparamlen, + int hash_idx, int padding, + int *stat, rsa_key *key) +{ + unsigned long modulus_bitlen, modulus_bytelen, x; + int err; + unsigned char *tmp; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(stat != NULL); + + /* default to invalid */ + *stat = 0; + + /* valid padding? */ + + if ((padding != LTC_LTC_PKCS_1_V1_5) && + (padding != LTC_LTC_PKCS_1_OAEP)) { + return CRYPT_PK_INVALID_PADDING; + } + + if (padding == LTC_LTC_PKCS_1_OAEP) { + /* valid hash ? */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + } + + /* get modulus len in bits */ + modulus_bitlen = mp_count_bits( (key->N)); + + /* outlen must be at least the size of the modulus */ + modulus_bytelen = mp_unsigned_bin_size( (key->N)); + if (modulus_bytelen != inlen) { + return CRYPT_INVALID_PACKET; + } + + /* allocate ram */ + tmp = XMALLOC(inlen); + if (tmp == NULL) { + return CRYPT_MEM; + } + + /* rsa decode the packet */ + x = inlen; + if ((err = ltc_mp.rsa_me(in, inlen, tmp, &x, PK_PRIVATE, key)) != CRYPT_OK) { + XFREE(tmp); + return err; + } + + if (padding == LTC_LTC_PKCS_1_OAEP) { + /* now OAEP decode the packet */ + err = pkcs_1_oaep_decode(tmp, x, lparam, lparamlen, modulus_bitlen, hash_idx, + out, outlen, stat); + } else { + /* now LTC_PKCS #1 v1.5 depad the packet */ + err = pkcs_1_v1_5_decode(tmp, x, LTC_LTC_PKCS_1_EME, modulus_bitlen, out, outlen, stat); + } + + XFREE(tmp); + return err; +} + +#endif /* LTC_MRSA */ + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c,v $ */ +/* $Revision: 1.10 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c b/core/lib/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c new file mode 100644 index 00000000000..60289d1ca34 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file rsa_encrypt_key.c + RSA LTC_PKCS #1 encryption, Tom St Denis and Andreas Lange +*/ + +#ifdef LTC_MRSA + +/** + (LTC_PKCS #1 v2.0) OAEP pad then encrypt + @param in The plaintext + @param inlen The length of the plaintext (octets) + @param out [out] The ciphertext + @param outlen [in/out] The max size and resulting size of the ciphertext + @param lparam The system "lparam" for the encryption + @param lparamlen The length of lparam (octets) + @param prng An active PRNG + @param prng_idx The index of the desired prng + @param hash_idx The index of the desired hash + @param padding Type of padding (LTC_LTC_PKCS_1_OAEP or LTC_LTC_PKCS_1_V1_5) + @param key The RSA key to encrypt to + @return CRYPT_OK if successful +*/ +int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const unsigned char *lparam, unsigned long lparamlen, + prng_state *prng, int prng_idx, int hash_idx, int padding, rsa_key *key) +{ + unsigned long modulus_bitlen, modulus_bytelen, x; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + /* valid padding? */ + if ((padding != LTC_LTC_PKCS_1_V1_5) && + (padding != LTC_LTC_PKCS_1_OAEP)) { + return CRYPT_PK_INVALID_PADDING; + } + + /* valid prng? */ + if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { + return err; + } + + if (padding == LTC_LTC_PKCS_1_OAEP) { + /* valid hash? */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + } + + /* get modulus len in bits */ + modulus_bitlen = mp_count_bits( (key->N)); + + /* outlen must be at least the size of the modulus */ + modulus_bytelen = mp_unsigned_bin_size( (key->N)); + if (modulus_bytelen > *outlen) { + *outlen = modulus_bytelen; + return CRYPT_BUFFER_OVERFLOW; + } + + if (padding == LTC_LTC_PKCS_1_OAEP) { + /* OAEP pad the key */ + x = *outlen; + if ((err = pkcs_1_oaep_encode(in, inlen, lparam, + lparamlen, modulus_bitlen, prng, prng_idx, hash_idx, + out, &x)) != CRYPT_OK) { + return err; + } + } else { + /* LTC_PKCS #1 v1.5 pad the key */ + x = *outlen; + if ((err = pkcs_1_v1_5_encode(in, inlen, LTC_LTC_PKCS_1_EME, + modulus_bitlen, prng, prng_idx, + out, &x)) != CRYPT_OK) { + return err; + } + } + + /* rsa exptmod the OAEP or LTC_PKCS #1 v1.5 pad */ + return ltc_mp.rsa_me(out, x, out, outlen, PK_PUBLIC, key); +} + +#endif /* LTC_MRSA */ + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c,v $ */ +/* $Revision: 1.10 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/rsa/rsa_export.c b/core/lib/libtomcrypt/src/pk/rsa/rsa_export.c new file mode 100644 index 00000000000..3434f3bc96b --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/rsa/rsa_export.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file rsa_export.c + Export RSA LTC_PKCS keys, Tom St Denis +*/ + +#ifdef LTC_MRSA + +/** + This will export either an RSAPublicKey or RSAPrivateKey [defined in LTC_PKCS #1 v2.1] + @param out [out] Destination of the packet + @param outlen [in/out] The max size and resulting size of the packet + @param type The type of exported key (PK_PRIVATE or PK_PUBLIC) + @param key The RSA key to export + @return CRYPT_OK if successful +*/ +int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key) +{ + unsigned long zero=0; + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + /* type valid? */ + if (!(key->type == PK_PRIVATE) && (type == PK_PRIVATE)) { + return CRYPT_PK_INVALID_TYPE; + } + + if (type == PK_PRIVATE) { + /* private key */ + /* output is + Version, n, e, d, p, q, d mod (p-1), d mod (q - 1), 1/q mod p + */ + return der_encode_sequence_multi(out, outlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &zero, + LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_INTEGER, 1UL, key->e, + LTC_ASN1_INTEGER, 1UL, key->d, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->dP, + LTC_ASN1_INTEGER, 1UL, key->dQ, + LTC_ASN1_INTEGER, 1UL, key->qP, + LTC_ASN1_EOL, 0UL, NULL); + } else { + /* public key */ + return der_encode_sequence_multi(out, outlen, + LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_INTEGER, 1UL, key->e, + LTC_ASN1_EOL, 0UL, NULL); + } +} + +#endif /* LTC_MRSA */ + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_export.c,v $ */ +/* $Revision: 1.17 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/rsa/rsa_exptmod.c b/core/lib/libtomcrypt/src/pk/rsa/rsa_exptmod.c new file mode 100644 index 00000000000..7db14ba6a1c --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/rsa/rsa_exptmod.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file rsa_exptmod.c + RSA LTC_PKCS exptmod, Tom St Denis +*/ + +#ifdef LTC_MRSA + +/** + Compute an RSA modular exponentiation + @param in The input data to send into RSA + @param inlen The length of the input (octets) + @param out [out] The destination + @param outlen [in/out] The max size and resulting size of the output + @param which Which exponent to use, e.g. PK_PRIVATE or PK_PUBLIC + @param key The RSA key to use + @return CRYPT_OK if successful +*/ +int rsa_exptmod(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int which, + rsa_key *key) +{ + void *tmp, *tmpa, *tmpb; + unsigned long x; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + /* is the key of the right type for the operation? */ + if (which == PK_PRIVATE && (key->type != PK_PRIVATE)) { + return CRYPT_PK_NOT_PRIVATE; + } + + /* must be a private or public operation */ + if (which != PK_PRIVATE && which != PK_PUBLIC) { + return CRYPT_PK_INVALID_TYPE; + } + + /* init and copy into tmp */ + if ((err = mp_init_multi(&tmp, &tmpa, &tmpb, NULL)) != CRYPT_OK) { return err; } + if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, (int)inlen)) != CRYPT_OK) { goto error; } + + /* sanity check on the input */ + if (mp_cmp(key->N, tmp) == LTC_MP_LT) { + err = CRYPT_PK_INVALID_SIZE; + goto error; + } + + /* are we using the private exponent and is the key optimized? */ +#ifdef LTC_LINARO_FIX_RSAWITHOUTCRT + if ((which == PK_PRIVATE) && (key->dP == NULL)) { + /* + * Fix when CRT optimization parameters are not there + * In such a case, we directly use the private key + */ + LTC_ARGCHK(key->dQ == NULL); + LTC_ARGCHK(key->qP == NULL); + LTC_ARGCHK(key->p == NULL); + LTC_ARGCHK(key->q == NULL); + /* exptmod it */ + if ((err = mp_exptmod(tmp, key->d, key->N, tmp)) != CRYPT_OK) { goto error; } + } else +#endif + if (which == PK_PRIVATE) { + /* tmpa = tmp^dP mod p */ + if ((err = mp_exptmod(tmp, key->dP, key->p, tmpa)) != CRYPT_OK) { goto error; } + + /* tmpb = tmp^dQ mod q */ + if ((err = mp_exptmod(tmp, key->dQ, key->q, tmpb)) != CRYPT_OK) { goto error; } + + /* tmp = (tmpa - tmpb) * qInv (mod p) */ + if ((err = mp_sub(tmpa, tmpb, tmp)) != CRYPT_OK) { goto error; } + if ((err = mp_mulmod(tmp, key->qP, key->p, tmp)) != CRYPT_OK) { goto error; } + + /* tmp = tmpb + q * tmp */ + if ((err = mp_mul(tmp, key->q, tmp)) != CRYPT_OK) { goto error; } + if ((err = mp_add(tmp, tmpb, tmp)) != CRYPT_OK) { goto error; } + } else { + /* exptmod it */ + if ((err = mp_exptmod(tmp, key->e, key->N, tmp)) != CRYPT_OK) { goto error; } + } + + /* read it back */ + x = (unsigned long)mp_unsigned_bin_size(key->N); + if (x > *outlen) { + *outlen = x; + err = CRYPT_BUFFER_OVERFLOW; + goto error; + } + + /* this should never happen ... */ + if (mp_unsigned_bin_size(tmp) > mp_unsigned_bin_size(key->N)) { + err = CRYPT_ERROR; + goto error; + } + *outlen = x; + + /* convert it */ + zeromem(out, x); + if ((err = mp_to_unsigned_bin(tmp, out+(x-mp_unsigned_bin_size(tmp)))) != CRYPT_OK) { goto error; } + + /* clean up and return */ + err = CRYPT_OK; +error: + mp_clear_multi(tmp, tmpa, tmpb, NULL); + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_exptmod.c,v $ */ +/* $Revision: 1.18 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/rsa/rsa_free.c b/core/lib/libtomcrypt/src/pk/rsa/rsa_free.c new file mode 100644 index 00000000000..cfc617c8485 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/rsa/rsa_free.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file rsa_free.c + Free an RSA key, Tom St Denis +*/ + +#ifdef LTC_MRSA + +/** + Free an RSA key from memory + @param key The RSA key to free +*/ +void rsa_free(rsa_key *key) +{ + LTC_ARGCHKVD(key != NULL); + mp_clear_multi(key->e, key->d, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL); +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_free.c,v $ */ +/* $Revision: 1.10 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/rsa/rsa_import.c b/core/lib/libtomcrypt/src/pk/rsa/rsa_import.c new file mode 100644 index 00000000000..67be63d462e --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/rsa/rsa_import.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file rsa_import.c + Import a LTC_PKCS RSA key, Tom St Denis +*/ + +#ifdef LTC_MRSA + +/** + Import an RSAPublicKey or RSAPrivateKey [two-prime only, only support >= 1024-bit keys, defined in LTC_PKCS #1 v2.1] + @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 rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key) +{ + int err; + void *zero; + unsigned char *tmpbuf; + unsigned long t, x, y, z, tmpoid[16]; + ltc_asn1_list ssl_pubkey_hashoid[2]; + ltc_asn1_list ssl_pubkey[2]; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* init key */ + if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, + &key->dP, &key->qP, &key->p, &key->q, NULL)) != CRYPT_OK) { + return err; + } + + /* see if the OpenSSL DER format RSA public key will work */ + tmpbuf = XCALLOC(1, MAX_RSA_SIZE*8); + if (tmpbuf == NULL) { + err = CRYPT_MEM; + goto LBL_ERR; + } + + /* this includes the internal hash ID and optional params (NULL in this case) */ + LTC_SET_ASN1(ssl_pubkey_hashoid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid)/sizeof(tmpoid[0])); + LTC_SET_ASN1(ssl_pubkey_hashoid, 1, LTC_ASN1_NULL, NULL, 0); + + /* 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 + */ + LTC_SET_ASN1(ssl_pubkey, 0, LTC_ASN1_SEQUENCE, &ssl_pubkey_hashoid, 2); + LTC_SET_ASN1(ssl_pubkey, 1, LTC_ASN1_BIT_STRING, tmpbuf, MAX_RSA_SIZE*8); + + if (der_decode_sequence(in, inlen, + ssl_pubkey, 2UL) == CRYPT_OK) { + + /* ok now we have to reassemble the BIT STRING to an OCTET STRING. Thanks OpenSSL... */ + for (t = y = z = x = 0; x < ssl_pubkey[1].size; x++) { + y = (y << 1) | tmpbuf[x]; + if (++z == 8) { + tmpbuf[t++] = (unsigned char)y; + y = 0; + z = 0; + } + } + + /* now it should be SEQUENCE { INTEGER, INTEGER } */ + if ((err = der_decode_sequence_multi(tmpbuf, t, + LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_INTEGER, 1UL, key->e, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + XFREE(tmpbuf); + goto LBL_ERR; + } + XFREE(tmpbuf); + key->type = PK_PUBLIC; + return CRYPT_OK; + } + XFREE(tmpbuf); + + /* not SSL public key, try to match against LTC_PKCS #1 standards */ + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + + if (mp_cmp_d(key->N, 0) == LTC_MP_EQ) { + if ((err = mp_init(&zero)) != CRYPT_OK) { + goto LBL_ERR; + } + /* it's a private key */ + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_INTEGER, 1UL, zero, + LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_INTEGER, 1UL, key->e, + LTC_ASN1_INTEGER, 1UL, key->d, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->dP, + LTC_ASN1_INTEGER, 1UL, key->dQ, + LTC_ASN1_INTEGER, 1UL, key->qP, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + mp_clear(zero); + goto LBL_ERR; + } + mp_clear(zero); + key->type = PK_PRIVATE; + } else if (mp_cmp_d(key->N, 1) == LTC_MP_EQ) { + /* we don't support multi-prime RSA */ + err = CRYPT_PK_INVALID_TYPE; + goto LBL_ERR; + } else { + /* it's a public key and we lack e */ + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_INTEGER, 1UL, key->e, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + key->type = PK_PUBLIC; + } + return CRYPT_OK; +LBL_ERR: + mp_clear_multi(key->d, key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL); + return err; +} + +#endif /* LTC_MRSA */ + + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_import.c,v $ */ +/* $Revision: 1.23 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/rsa/rsa_make_key.c b/core/lib/libtomcrypt/src/pk/rsa/rsa_make_key.c new file mode 100644 index 00000000000..b97166fa7b7 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/rsa/rsa_make_key.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file rsa_make_key.c + RSA key generation, Tom St Denis +*/ + +#ifdef LTC_MRSA + +/** + Create an RSA key + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param size The size of the modulus (key size) desired (octets) + @param e The "e" value (public key). e==65537 is a good choice + @param key [out] Destination of a newly created private key pair + @return CRYPT_OK if successful, upon error all allocated ram is freed +*/ +int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key) +{ + void *p, *q, *tmp1, *tmp2, *tmp3; + int err; + + LTC_ARGCHK(ltc_mp.name != NULL); + LTC_ARGCHK(key != NULL); + + if ((size < (MIN_RSA_SIZE/8)) || (size > (MAX_RSA_SIZE/8))) { + return CRYPT_INVALID_KEYSIZE; + } + + if ((e < 3) || ((e & 1) == 0)) { + return CRYPT_INVALID_ARG; + } + + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != CRYPT_OK) { + return err; + } + + /* make primes p and q (optimization provided by Wayne Scott) */ + if ((err = mp_set_int(tmp3, e)) != CRYPT_OK) { goto errkey; } /* tmp3 = e */ + + /* make prime "p" */ + do { + if ((err = rand_prime( p, size/2, prng, wprng)) != CRYPT_OK) { goto errkey; } + if ((err = mp_sub_d( p, 1, tmp1)) != CRYPT_OK) { goto errkey; } /* tmp1 = p-1 */ + if ((err = mp_gcd( tmp1, tmp3, tmp2)) != CRYPT_OK) { goto errkey; } /* tmp2 = gcd(p-1, e) */ + } while (mp_cmp_d( tmp2, 1) != 0); /* while e divides p-1 */ + + /* make prime "q" */ + do { + if ((err = rand_prime( q, size/2, prng, wprng)) != CRYPT_OK) { goto errkey; } + if ((err = mp_sub_d( q, 1, tmp1)) != CRYPT_OK) { goto errkey; } /* tmp1 = q-1 */ + if ((err = mp_gcd( tmp1, tmp3, tmp2)) != CRYPT_OK) { goto errkey; } /* tmp2 = gcd(q-1, e) */ + } while (mp_cmp_d( tmp2, 1) != 0); /* while e divides q-1 */ + + /* tmp1 = lcm(p-1, q-1) */ + if ((err = mp_sub_d( p, 1, tmp2)) != CRYPT_OK) { goto errkey; } /* tmp2 = p-1 */ + /* tmp1 = q-1 (previous do/while loop) */ + if ((err = mp_lcm( tmp1, tmp2, tmp1)) != CRYPT_OK) { goto errkey; } /* tmp1 = lcm(p-1, q-1) */ + + /* make key */ + if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL)) != CRYPT_OK) { + goto errkey; + } + + if ((err = mp_set_int( key->e, e)) != CRYPT_OK) { goto errkey; } /* key->e = e */ + if ((err = mp_invmod( key->e, tmp1, key->d)) != CRYPT_OK) { goto errkey; } /* key->d = 1/e mod lcm(p-1,q-1) */ + if ((err = mp_mul( p, q, key->N)) != CRYPT_OK) { goto errkey; } /* key->N = pq */ + + /* optimize for CRT now */ + /* find d mod q-1 and d mod p-1 */ + if ((err = mp_sub_d( p, 1, tmp1)) != CRYPT_OK) { goto errkey; } /* tmp1 = q-1 */ + if ((err = mp_sub_d( q, 1, tmp2)) != CRYPT_OK) { goto errkey; } /* tmp2 = p-1 */ + if ((err = mp_mod( key->d, tmp1, key->dP)) != CRYPT_OK) { goto errkey; } /* dP = d mod p-1 */ + if ((err = mp_mod( key->d, tmp2, key->dQ)) != CRYPT_OK) { goto errkey; } /* dQ = d mod q-1 */ + if ((err = mp_invmod( q, p, key->qP)) != CRYPT_OK) { goto errkey; } /* qP = 1/q mod p */ + + if ((err = mp_copy( p, key->p)) != CRYPT_OK) { goto errkey; } + if ((err = mp_copy( q, key->q)) != CRYPT_OK) { goto errkey; } + + /* set key type (in this case it's CRT optimized) */ + key->type = PK_PRIVATE; + + /* return ok and free temps */ + err = CRYPT_OK; + goto cleanup; +errkey: + mp_clear_multi(key->d, key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL); +cleanup: + mp_clear_multi(tmp3, tmp2, tmp1, p, q, NULL); + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_make_key.c,v $ */ +/* $Revision: 1.16 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/rsa/rsa_sign_hash.c b/core/lib/libtomcrypt/src/pk/rsa/rsa_sign_hash.c new file mode 100644 index 00000000000..47462cb61d4 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/rsa/rsa_sign_hash.c @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file rsa_sign_hash.c + RSA LTC_PKCS #1 v1.5 and v2 PSS sign hash, Tom St Denis and Andreas Lange +*/ + +#ifdef LTC_MRSA + +/** + LTC_PKCS #1 pad then sign + @param in The hash to sign + @param inlen The length of the hash to sign (octets) + @param out [out] The signature + @param outlen [in/out] The max size and resulting size of the signature + @param padding Type of padding (LTC_LTC_PKCS_1_PSS or LTC_LTC_PKCS_1_V1_5) + @param prng An active PRNG state + @param prng_idx The index of the PRNG desired + @param hash_idx The index of the hash desired + @param saltlen The length of the salt desired (octets) + @param key The private RSA key to use + @return CRYPT_OK if successful +*/ +int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + int padding, + prng_state *prng, int prng_idx, + int hash_idx, unsigned long saltlen, + rsa_key *key) +{ + unsigned long modulus_bitlen, modulus_bytelen, x, y; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + /* valid padding? */ + if ((padding != LTC_LTC_PKCS_1_V1_5) && (padding != LTC_LTC_PKCS_1_PSS)) { + return CRYPT_PK_INVALID_PADDING; + } + + if (padding == LTC_LTC_PKCS_1_PSS) { + /* valid prng and hash ? */ + if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { + return err; + } + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + } + + /* get modulus len in bits */ + modulus_bitlen = mp_count_bits((key->N)); + + /* outlen must be at least the size of the modulus */ + modulus_bytelen = mp_unsigned_bin_size((key->N)); + if (modulus_bytelen > *outlen) { + *outlen = modulus_bytelen; + return CRYPT_BUFFER_OVERFLOW; + } + + if (padding == LTC_LTC_PKCS_1_PSS) { + /* PSS pad the key */ + x = *outlen; + if ((err = pkcs_1_pss_encode(in, inlen, saltlen, prng, prng_idx, + hash_idx, modulus_bitlen, out, &x)) != CRYPT_OK) { + return err; + } + } else { + /* LTC_PKCS #1 v1.5 pad the hash */ + unsigned char *tmpin; + ltc_asn1_list digestinfo[2], siginfo[2]; + + /* not all hashes have OIDs... so sad */ + if (hash_descriptor[hash_idx].OIDlen == 0) { + return CRYPT_INVALID_ARG; + } + + /* construct the SEQUENCE + SEQUENCE { + SEQUENCE {hashoid OID + blah NULL + } + hash OCTET STRING + } + */ + LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash_idx].OID, hash_descriptor[hash_idx].OIDlen); + LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0); + LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2); + LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, in, inlen); + + /* allocate memory for the encoding */ + y = mp_unsigned_bin_size(key->N); + tmpin = XMALLOC(y); + if (tmpin == NULL) { + return CRYPT_MEM; + } + + if ((err = der_encode_sequence(siginfo, 2, tmpin, &y)) != CRYPT_OK) { + XFREE(tmpin); + return err; + } + + x = *outlen; + if ((err = pkcs_1_v1_5_encode(tmpin, y, LTC_LTC_PKCS_1_EMSA, + modulus_bitlen, NULL, 0, + out, &x)) != CRYPT_OK) { + XFREE(tmpin); + return err; + } + XFREE(tmpin); + } + + /* RSA encode it */ + return ltc_mp.rsa_me(out, x, out, outlen, PK_PRIVATE, key); +} + +#endif /* LTC_MRSA */ + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_sign_hash.c,v $ */ +/* $Revision: 1.11 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/rsa/rsa_verify_hash.c b/core/lib/libtomcrypt/src/pk/rsa/rsa_verify_hash.c new file mode 100644 index 00000000000..6ecb4df27d4 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/rsa/rsa_verify_hash.c @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file rsa_verify_hash.c + RSA LTC_PKCS #1 v1.5 or v2 PSS signature verification, Tom St Denis and Andreas Lange +*/ + +#ifdef LTC_MRSA + +/** + LTC_PKCS #1 de-sign then v1.5 or PSS depad + @param sig The signature data + @param siglen The length of the signature data (octets) + @param hash The hash of the message that was signed + @param hashlen The length of the hash of the message that was signed (octets) + @param padding Type of padding (LTC_LTC_PKCS_1_PSS or LTC_LTC_PKCS_1_V1_5) + @param hash_idx The index of the desired hash + @param saltlen The length of the salt used during signature + @param stat [out] The result of the signature comparison, 1==valid, 0==invalid + @param key The public RSA key corresponding to the key that performed the signature + @return CRYPT_OK on success (even if the signature is invalid) +*/ +int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int padding, + int hash_idx, unsigned long saltlen, + int *stat, rsa_key *key) +{ + unsigned long modulus_bitlen, modulus_bytelen, x; + int err; + unsigned char *tmpbuf; + + LTC_ARGCHK(hash != NULL); + LTC_ARGCHK(sig != NULL); + LTC_ARGCHK(stat != NULL); + LTC_ARGCHK(key != NULL); + + /* default to invalid */ + *stat = 0; + + /* valid padding? */ + + if ((padding != LTC_LTC_PKCS_1_V1_5) && + (padding != LTC_LTC_PKCS_1_PSS)) { + return CRYPT_PK_INVALID_PADDING; + } + + if (padding == LTC_LTC_PKCS_1_PSS) { + /* valid hash ? */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + } + + /* get modulus len in bits */ + modulus_bitlen = mp_count_bits( (key->N)); + + /* outlen must be at least the size of the modulus */ + modulus_bytelen = mp_unsigned_bin_size( (key->N)); + if (modulus_bytelen != siglen) { + return CRYPT_INVALID_PACKET; + } + + /* allocate temp buffer for decoded sig */ + tmpbuf = XMALLOC(siglen); + if (tmpbuf == NULL) { + return CRYPT_MEM; + } + + /* RSA decode it */ + x = siglen; + if ((err = ltc_mp.rsa_me(sig, siglen, tmpbuf, &x, PK_PUBLIC, key)) != CRYPT_OK) { + XFREE(tmpbuf); + return err; + } + + /* make sure the output is the right size */ + if (x != siglen) { + XFREE(tmpbuf); + return CRYPT_INVALID_PACKET; + } + + if (padding == LTC_LTC_PKCS_1_PSS) { + /* PSS decode and verify it */ + err = pkcs_1_pss_decode(hash, hashlen, tmpbuf, x, saltlen, hash_idx, modulus_bitlen, stat); + } else { + /* LTC_PKCS #1 v1.5 decode it */ + unsigned char *out; + unsigned long outlen, loid[16]; + int decoded; + ltc_asn1_list digestinfo[2], siginfo[2]; + + /* not all hashes have OIDs... so sad */ + if (hash_descriptor[hash_idx].OIDlen == 0) { + err = CRYPT_INVALID_ARG; + goto bail_2; + } + + /* allocate temp buffer for decoded hash */ + outlen = ((modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0)) - 3; + out = XMALLOC(outlen); + if (out == NULL) { + err = CRYPT_MEM; + goto bail_2; + } + + if ((err = pkcs_1_v1_5_decode(tmpbuf, x, LTC_LTC_PKCS_1_EMSA, modulus_bitlen, out, &outlen, &decoded)) != CRYPT_OK) { + XFREE(out); + goto bail_2; + } + + /* now we must decode out[0...outlen-1] using ASN.1, test the OID and then test the hash */ + /* construct the SEQUENCE + SEQUENCE { + SEQUENCE {hashoid OID + blah NULL + } + hash OCTET STRING + } + */ + LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, loid, sizeof(loid)/sizeof(loid[0])); + LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0); + 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) { + XFREE(out); + goto bail_2; + } + + /* test OID */ + if ((digestinfo[0].size == hash_descriptor[hash_idx].OIDlen) && + (XMEMCMP(digestinfo[0].data, hash_descriptor[hash_idx].OID, sizeof(unsigned long) * hash_descriptor[hash_idx].OIDlen) == 0) && + (siginfo[1].size == hashlen) && + (XMEMCMP(siginfo[1].data, hash, hashlen) == 0)) { + *stat = 1; + } + +#ifdef LTC_CLEAN_STACK + zeromem(out, outlen); +#endif + XFREE(out); + } + +bail_2: +#ifdef LTC_CLEAN_STACK + zeromem(tmpbuf, siglen); +#endif + XFREE(tmpbuf); + return err; +} + +#endif /* LTC_MRSA */ + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_verify_hash.c,v $ */ +/* $Revision: 1.13 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/pk/rsa/sub.mk b/core/lib/libtomcrypt/src/pk/rsa/sub.mk new file mode 100644 index 00000000000..b72a7c000dc --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/rsa/sub.mk @@ -0,0 +1,9 @@ +srcs-y += rsa_decrypt_key.c +srcs-y += rsa_encrypt_key.c +srcs-y += rsa_export.c +srcs-y += rsa_exptmod.c +srcs-y += rsa_free.c +srcs-y += rsa_import.c +srcs-y += rsa_make_key.c +srcs-y += rsa_sign_hash.c +srcs-y += rsa_verify_hash.c diff --git a/core/lib/libtomcrypt/src/pk/sub.mk b/core/lib/libtomcrypt/src/pk/sub.mk new file mode 100644 index 00000000000..83559533d69 --- /dev/null +++ b/core/lib/libtomcrypt/src/pk/sub.mk @@ -0,0 +1,6 @@ +subdirs-y += asn1 +subdirs-y += dsa +subdirs-y += ecc +subdirs-y += pkcs1 +subdirs-y += rsa +subdirs-y += dh diff --git a/core/lib/libtomcrypt/src/prngs/rng_get_bytes.c b/core/lib/libtomcrypt/src/prngs/rng_get_bytes.c new file mode 100644 index 00000000000..fd6ce878fd0 --- /dev/null +++ b/core/lib/libtomcrypt/src/prngs/rng_get_bytes.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file rng_get_bytes.c + portable way to get secure random bits to feed a PRNG (Tom St Denis) +*/ + +#ifdef LTC_DEVRANDOM +/* on *NIX read /dev/random */ +static unsigned long rng_nix(unsigned char *buf, unsigned long len, + void (*callback)(void)) +{ +#ifdef LTC_NO_FILE + return 0; +#else + FILE *f; + unsigned long x; +#ifdef TRY_URANDOM_FIRST + f = fopen("/dev/urandom", "rb"); + if (f == NULL) +#endif /* TRY_URANDOM_FIRST */ + f = fopen("/dev/random", "rb"); + + if (f == NULL) { + return 0; + } + + /* disable buffering */ + if (setvbuf(f, NULL, _IONBF, 0) != 0) { + fclose(f); + return 0; + } + + x = (unsigned long)fread(buf, 1, (size_t)len, f); + fclose(f); + return x; +#endif /* LTC_NO_FILE */ +} + +#endif /* LTC_DEVRANDOM */ + +/* on ANSI C platforms with 100 < CLOCKS_PER_SEC < 10000 */ +#if defined(CLOCKS_PER_SEC) && !defined(WINCE) + +#define ANSI_RNG + +static unsigned long rng_ansic(unsigned char *buf, unsigned long len, + void (*callback)(void)) +{ + clock_t t1; + int l, acc, bits, a, b; + + if (XCLOCKS_PER_SEC < 100 || XCLOCKS_PER_SEC > 10000) { + return 0; + } + + l = len; + bits = 8; + acc = a = b = 0; + while (len--) { + if (callback != NULL) callback(); + while (bits--) { + do { + t1 = XCLOCK(); while (t1 == XCLOCK()) a ^= 1; + t1 = XCLOCK(); while (t1 == XCLOCK()) b ^= 1; + } while (a == b); + acc = (acc << 1) | a; + } + *buf++ = acc; + acc = 0; + bits = 8; + } + acc = bits = a = b = 0; + return l; +} + +#endif + +/* Try the Microsoft CSP */ +#if defined(WIN32) || defined(WINCE) +#define _WIN32_WINNT 0x0400 +#ifdef WINCE + #define UNDER_CE + #define ARM +#endif +#include +#include + +static unsigned long rng_win32(unsigned char *buf, unsigned long len, + void (*callback)(void)) +{ + HCRYPTPROV hProv = 0; + if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, + (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) && + !CryptAcquireContext (&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET)) + return 0; + + if (CryptGenRandom(hProv, len, buf) == TRUE) { + CryptReleaseContext(hProv, 0); + return len; + } else { + CryptReleaseContext(hProv, 0); + return 0; + } +} + +#endif /* WIN32 */ + +/** + Read the system RNG + @param out Destination + @param outlen Length desired (octets) + @param callback Pointer to void function to act as "callback" when RNG is slow. This can be NULL + @return Number of octets read +*/ +unsigned long rng_get_bytes(unsigned char *out, unsigned long outlen, + void (*callback)(void)) +{ + unsigned long x; + + LTC_ARGCHK(out != NULL); + +#if defined(LTC_DEVRANDOM) + x = rng_nix(out, outlen, callback); if (x != 0) { return x; } +#endif +#ifdef WIN32 + x = rng_win32(out, outlen, callback); if (x != 0) { return x; } +#endif +#ifdef ANSI_RNG + x = rng_ansic(out, outlen, callback); if (x != 0) { return x; } +#endif + return 0; +} + +/* $Source: /cvs/libtom/libtomcrypt/src/prngs/rng_get_bytes.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/prngs/rng_make_prng.c b/core/lib/libtomcrypt/src/prngs/rng_make_prng.c new file mode 100644 index 00000000000..87527fc0d61 --- /dev/null +++ b/core/lib/libtomcrypt/src/prngs/rng_make_prng.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file rng_make_prng.c + portable way to get secure random bits to feed a PRNG (Tom St Denis) +*/ + +/** + Create a PRNG from a RNG + @param bits Number of bits of entropy desired (64 ... 1024) + @param wprng Index of which PRNG to setup + @param prng [out] PRNG state to initialize + @param callback A pointer to a void function for when the RNG is slow, this can be NULL + @return CRYPT_OK if successful +*/ +int rng_make_prng(int bits, int wprng, prng_state *prng, + void (*callback)(void)) +{ + unsigned char buf[256]; + int err; + + LTC_ARGCHK(prng != NULL); + + /* check parameter */ + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + if (bits < 64 || bits > 1024) { + return CRYPT_INVALID_PRNGSIZE; + } + + if ((err = prng_descriptor[wprng].start(prng)) != CRYPT_OK) { + return err; + } + + bits = ((bits/8)+((bits&7)!=0?1:0)) * 2; + if (rng_get_bytes(buf, (unsigned long)bits, callback) != (unsigned long)bits) { + return CRYPT_ERROR_READPRNG; + } + + if ((err = prng_descriptor[wprng].add_entropy(buf, (unsigned long)bits, prng)) != CRYPT_OK) { + return err; + } + + if ((err = prng_descriptor[wprng].ready(prng)) != CRYPT_OK) { + return err; + } + + #ifdef LTC_CLEAN_STACK + zeromem(buf, sizeof(buf)); + #endif + return CRYPT_OK; +} + + +/* $Source: /cvs/libtom/libtomcrypt/src/prngs/rng_make_prng.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/core/lib/libtomcrypt/src/prngs/sprng.c b/core/lib/libtomcrypt/src/prngs/sprng.c new file mode 100644 index 00000000000..729b53a894a --- /dev/null +++ b/core/lib/libtomcrypt/src/prngs/sprng.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file sprng.c + Secure PRNG, Tom St Denis +*/ + +/* A secure PRNG using the RNG functions. Basically this is a + * wrapper that allows you to use a secure RNG as a PRNG + * in the various other functions. + */ + +#ifdef LTC_SPRNG + +const struct ltc_prng_descriptor sprng_desc = +{ + "sprng", 0, + &sprng_start, + &sprng_add_entropy, + &sprng_ready, + &sprng_read, + &sprng_done, + &sprng_export, + &sprng_import, + &sprng_test +}; + +/** + Start the PRNG + @param prng [out] The PRNG state to initialize + @return CRYPT_OK if successful +*/ +int sprng_start(prng_state *prng) +{ + return CRYPT_OK; +} + +/** + Add entropy to the PRNG state + @param in The data to add + @param inlen Length of the data to add + @param prng PRNG state to update + @return CRYPT_OK if successful +*/ +int sprng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + return CRYPT_OK; +} + +/** + Make the PRNG ready to read from + @param prng The PRNG to make active + @return CRYPT_OK if successful +*/ +int sprng_ready(prng_state *prng) +{ + return CRYPT_OK; +} + +/** + Read from the PRNG + @param out Destination + @param outlen Length of output + @param prng The active PRNG to read from + @return Number of octets read +*/ +unsigned long sprng_read(unsigned char *out, unsigned long outlen, prng_state *prng) +{ + LTC_ARGCHK(out != NULL); + return rng_get_bytes(out, outlen, NULL); +} + +/** + Terminate the PRNG + @param prng The PRNG to terminate + @return CRYPT_OK if successful +*/ +int sprng_done(prng_state *prng) +{ + return CRYPT_OK; +} + +/** + Export the PRNG state + @param out [out] Destination + @param outlen [in/out] Max size and resulting size of the state + @param prng The PRNG to export + @return CRYPT_OK if successful +*/ +int sprng_export(unsigned char *out, unsigned long *outlen, prng_state *prng) +{ + LTC_ARGCHK(outlen != NULL); + + *outlen = 0; + return CRYPT_OK; +} + +/** + Import a PRNG state + @param in The PRNG state + @param inlen Size of the state + @param prng The PRNG to import + @return CRYPT_OK if successful +*/ +int sprng_import(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + return CRYPT_OK; +} + +/** + PRNG self-test + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled +*/ +int sprng_test(void) +{ + return CRYPT_OK; +} + +#endif + + + + +/* $Source: /cvs/libtom/libtomcrypt/src/prngs/sprng.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/prngs/sub.mk b/core/lib/libtomcrypt/src/prngs/sub.mk new file mode 100644 index 00000000000..a6d5bf89d46 --- /dev/null +++ b/core/lib/libtomcrypt/src/prngs/sub.mk @@ -0,0 +1,6 @@ +cflags-y += -Wno-unused-parameter -Wno-unused-variable + +srcs-y += rng_get_bytes.c +srcs-y += rng_make_prng.c +srcs-y += sprng.c +srcs-y += yarrow.c diff --git a/core/lib/libtomcrypt/src/prngs/yarrow.c b/core/lib/libtomcrypt/src/prngs/yarrow.c new file mode 100644 index 00000000000..a0b9c731832 --- /dev/null +++ b/core/lib/libtomcrypt/src/prngs/yarrow.c @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file yarrow.c + Yarrow PRNG, Tom St Denis +*/ + +#ifdef LTC_YARROW + +const struct ltc_prng_descriptor yarrow_desc = +{ + "yarrow", 64, + &yarrow_start, + &yarrow_add_entropy, + &yarrow_ready, + &yarrow_read, + &yarrow_done, + &yarrow_export, + &yarrow_import, + &yarrow_test +}; + +/** + Start the PRNG + @param prng [out] The PRNG state to initialize + @return CRYPT_OK if successful +*/ +int yarrow_start(prng_state *prng) +{ + int err; + + LTC_ARGCHK(prng != NULL); + + /* these are the default hash/cipher combo used */ +#ifdef LTC_RIJNDAEL +#if LTC_YARROW_AES==0 + prng->yarrow.cipher = register_cipher(&rijndael_enc_desc); +#elif LTC_YARROW_AES==1 + prng->yarrow.cipher = register_cipher(&aes_enc_desc); +#elif LTC_YARROW_AES==2 + prng->yarrow.cipher = register_cipher(&rijndael_desc); +#elif LTC_YARROW_AES==3 + prng->yarrow.cipher = register_cipher(&aes_desc); +#endif +#elif defined(LTC_BLOWFISH) + prng->yarrow.cipher = register_cipher(&blowfish_desc); +#elif defined(LTC_TWOFISH) + prng->yarrow.cipher = register_cipher(&twofish_desc); +#elif defined(LTC_RC6) + prng->yarrow.cipher = register_cipher(&rc6_desc); +#elif defined(LTC_RC5) + prng->yarrow.cipher = register_cipher(&rc5_desc); +#elif defined(LTC_SAFERP) + prng->yarrow.cipher = register_cipher(&saferp_desc); +#elif defined(LTC_RC2) + prng->yarrow.cipher = register_cipher(&rc2_desc); +#elif defined(LTC_NOEKEON) + prng->yarrow.cipher = register_cipher(&noekeon_desc); +#elif defined(LTC_ANUBIS) + prng->yarrow.cipher = register_cipher(&anubis_desc); +#elif defined(LTC_KSEED) + prng->yarrow.cipher = register_cipher(&kseed_desc); +#elif defined(LTC_KHAZAD) + prng->yarrow.cipher = register_cipher(&khazad_desc); +#elif defined(LTC_CAST5) + prng->yarrow.cipher = register_cipher(&cast5_desc); +#elif defined(LTC_XTEA) + prng->yarrow.cipher = register_cipher(&xtea_desc); +#elif defined(LTC_SAFER) + prng->yarrow.cipher = register_cipher(&safer_sk128_desc); +#elif defined(LTC_DES) + prng->yarrow.cipher = register_cipher(&des3_desc); +#else + #error LTC_YARROW needs at least one CIPHER +#endif + if ((err = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) { + return err; + } + +#ifdef LTC_SHA256 + prng->yarrow.hash = register_hash(&sha256_desc); +#elif defined(LTC_SHA512) + prng->yarrow.hash = register_hash(&sha512_desc); +#elif defined(LTC_TIGER) + prng->yarrow.hash = register_hash(&tiger_desc); +#elif defined(LTC_SHA1) + prng->yarrow.hash = register_hash(&sha1_desc); +#elif defined(LTC_RIPEMD320) + prng->yarrow.hash = register_hash(&rmd320_desc); +#elif defined(LTC_RIPEMD256) + prng->yarrow.hash = register_hash(&rmd256_desc); +#elif defined(LTC_RIPEMD160) + prng->yarrow.hash = register_hash(&rmd160_desc); +#elif defined(LTC_RIPEMD128) + prng->yarrow.hash = register_hash(&rmd128_desc); +#elif defined(LTC_MD5) + prng->yarrow.hash = register_hash(&md5_desc); +#elif defined(LTC_MD4) + prng->yarrow.hash = register_hash(&md4_desc); +#elif defined(LTC_MD2) + prng->yarrow.hash = register_hash(&md2_desc); +#elif defined(LTC_WHIRLPOOL) + prng->yarrow.hash = register_hash(&whirlpool_desc); +#else + #error LTC_YARROW needs at least one HASH +#endif + if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) { + return err; + } + + /* zero the memory used */ + zeromem(prng->yarrow.pool, sizeof(prng->yarrow.pool)); + LTC_MUTEX_INIT(&prng->yarrow.prng_lock) + + return CRYPT_OK; +} + +/** + Add entropy to the PRNG state + @param in The data to add + @param inlen Length of the data to add + @param prng PRNG state to update + @return CRYPT_OK if successful +*/ +int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + hash_state md; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); + + if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return err; + } + + /* start the hash */ + if ((err = hash_descriptor[prng->yarrow.hash].init(&md)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return err; + } + + /* hash the current pool */ + if ((err = hash_descriptor[prng->yarrow.hash].process(&md, prng->yarrow.pool, + hash_descriptor[prng->yarrow.hash].hashsize)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return err; + } + + /* add the new entropy */ + if ((err = hash_descriptor[prng->yarrow.hash].process(&md, in, inlen)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return err; + } + + /* store result */ + if ((err = hash_descriptor[prng->yarrow.hash].done(&md, prng->yarrow.pool)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return err; + } + + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return CRYPT_OK; +} + +/** + Make the PRNG ready to read from + @param prng The PRNG to make active + @return CRYPT_OK if successful +*/ +int yarrow_ready(prng_state *prng) +{ + int ks, err; + + LTC_ARGCHK(prng != NULL); + LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); + + if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return err; + } + + if ((err = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return err; + } + + /* setup CTR mode using the "pool" as the key */ + ks = (int)hash_descriptor[prng->yarrow.hash].hashsize; + if ((err = cipher_descriptor[prng->yarrow.cipher].keysize(&ks)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return err; + } + + if ((err = ctr_start(prng->yarrow.cipher, /* what cipher to use */ + prng->yarrow.pool, /* IV */ + prng->yarrow.pool, ks, /* KEY and key size */ + 0, /* number of rounds */ + CTR_COUNTER_LITTLE_ENDIAN, /* little endian counter */ + &prng->yarrow.ctr)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return err; + } + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return CRYPT_OK; +} + +/** + Read from the PRNG + @param out Destination + @param outlen Length of output + @param prng The active PRNG to read from + @return Number of octets read +*/ +unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng) +{ + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); + + /* put out in predictable state first */ + zeromem(out, outlen); + + /* now randomize it */ + if (ctr_encrypt(out, out, outlen, &prng->yarrow.ctr) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return 0; + } + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return outlen; +} + +/** + Terminate the PRNG + @param prng The PRNG to terminate + @return CRYPT_OK if successful +*/ +int yarrow_done(prng_state *prng) +{ + int err; + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); + + /* call cipher done when we invent one ;-) */ + + /* we invented one */ + err = ctr_done(&prng->yarrow.ctr); + + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return err; +} + +/** + Export the PRNG state + @param out [out] Destination + @param outlen [in/out] Max size and resulting size of the state + @param prng The PRNG to export + @return CRYPT_OK if successful +*/ +int yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng) +{ + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); + + /* we'll write 64 bytes for s&g's */ + if (*outlen < 64) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + *outlen = 64; + return CRYPT_BUFFER_OVERFLOW; + } + + if (yarrow_read(out, 64, prng) != 64) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return CRYPT_ERROR_READPRNG; + } + *outlen = 64; + + return CRYPT_OK; +} + +/** + Import a PRNG state + @param in The PRNG state + @param inlen Size of the state + @param prng The PRNG to import + @return CRYPT_OK if successful +*/ +int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); + + if (inlen != 64) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return CRYPT_INVALID_ARG; + } + + if ((err = yarrow_start(prng)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return err; + } + err = yarrow_add_entropy(in, 64, prng); + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return err; +} + +/** + PRNG self-test + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled +*/ +int yarrow_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + int err; + prng_state prng; + + if ((err = yarrow_start(&prng)) != CRYPT_OK) { + return err; + } + + /* now let's test the hash/cipher that was chosen */ + if ((err = cipher_descriptor[prng.yarrow.cipher].test()) != CRYPT_OK) { + return err; + } + if ((err = hash_descriptor[prng.yarrow.hash].test()) != CRYPT_OK) { + return err; + } + + return CRYPT_OK; +#endif +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/prngs/yarrow.c,v $ */ +/* $Revision: 1.16 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/src/sub.mk b/core/lib/libtomcrypt/src/sub.mk new file mode 100644 index 00000000000..1adee90aa89 --- /dev/null +++ b/core/lib/libtomcrypt/src/sub.mk @@ -0,0 +1,18 @@ +srcs-y += mpa_desc.c +# Get mpa.h which normally is an internal .h file +cppflags-mpa_desc.c-y += -Ilib/libmpa +cflags-mpa_desc.c-y += -Wno-declaration-after-statement +cflags-mpa_desc.c-y += -Wno-unused-parameter + +srcs-y += tee_ltc_wrapper.c +cflags-tee_ltc_wrapper.c-y += -Wno-unused-parameter + +subdirs-y += ciphers +subdirs-y += encauth +subdirs-y += hashes +subdirs-y += mac +subdirs-y += math +subdirs-y += misc +subdirs-y += modes +subdirs-y += pk +subdirs-y += prngs diff --git a/core/lib/libtomcrypt/src/tee_ltc_wrapper.c b/core/lib/libtomcrypt/src/tee_ltc_wrapper.c new file mode 100644 index 00000000000..ab78c23f47b --- /dev/null +++ b/core/lib/libtomcrypt/src/tee_ltc_wrapper.c @@ -0,0 +1,403 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tee_ltc_wrapper.h" +#include "tee_api_defines.h" +#include "tomcrypt_mpa.h" + +#define LTC_VARIABLE_NUMBER (50) + +static uint32_t _ltc_mempool_u32[mpa_scratch_mem_size_in_U32( + LTC_VARIABLE_NUMBER, LTC_MAX_BITS_PER_VARIABLE) ]; + +static void tee_ltc_alloc_mpa(void) +{ + mpa_scratch_mem pool; + pool = (mpa_scratch_mem_base *) &_ltc_mempool_u32; + init_mpa_tomcrypt(pool); + mpa_init_scratch_mem(pool, LTC_VARIABLE_NUMBER, LTC_MAX_BITS_PER_VARIABLE); +} + +static void tee_ltc_dealloc_mpa(void) +{ + /* + * Nothing to be done as the memory is static + */ +} + +/* Random generator */ +static int prng_mpa_start(prng_state *prng) +{ + return CRYPT_OK; +} + +static int prng_mpa_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + // No entropy is required + return CRYPT_OK; +} + +static int prng_mpa_ready(prng_state *prng) +{ + return CRYPT_OK; +} + +extern TEE_Result get_rng_array(void *buf, size_t blen); +static unsigned long prng_mpa_read(unsigned char *out, unsigned long outlen, prng_state *prng) +{ + if (TEE_SUCCESS == get_rng_array(out, outlen)) + return outlen; + else + return 0; +} + +static int prng_mpa_done(prng_state *prng) +{ + return CRYPT_OK; +} + +static int prng_mpa_export(unsigned char *out, unsigned long *outlen, prng_state *prng) +{ + return CRYPT_OK; +} + +static int prng_mpa_import(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + return CRYPT_OK; +} + +static int prng_mpa_test(void) +{ + return CRYPT_OK; +} + +static const struct ltc_prng_descriptor prng_mpa_desc = +{ + .name = "prng_mpa", + .export_size = 64, + .start = &prng_mpa_start, + .add_entropy = &prng_mpa_add_entropy, + .ready = &prng_mpa_ready, + .read = &prng_mpa_read, + .done = &prng_mpa_done, + .pexport = &prng_mpa_export, + .pimport = &prng_mpa_import, + .test = &prng_mpa_test, +}; + +/* + * tee_ltc_reg_algs(): Registers + * - algorithms + * - hash + * - prng (pseudo random generator) + * This function is copied from reg_algs() from libtomcrypt/test/x86_prof.c + */ + +static void tee_ltc_reg_algs(void) +{ +#ifdef LTC_RIJNDAEL + register_cipher (&aes_desc); +#endif +#ifdef LTC_BLOWFISH + register_cipher (&blowfish_desc); +#endif +#ifdef LTC_XTEA + register_cipher (&xtea_desc); +#endif +#ifdef LTC_RC5 + register_cipher (&rc5_desc); +#endif +#ifdef LTC_RC6 + register_cipher (&rc6_desc); +#endif +#ifdef LTC_SAFERP + register_cipher (&saferp_desc); +#endif +#ifdef LTC_TWOFISH + register_cipher (&twofish_desc); +#endif +#ifdef LTC_SAFER + register_cipher (&safer_k64_desc); + register_cipher (&safer_sk64_desc); + register_cipher (&safer_k128_desc); + register_cipher (&safer_sk128_desc); +#endif +#ifdef LTC_RC2 + register_cipher (&rc2_desc); +#endif +#ifdef LTC_DES + register_cipher (&des_desc); + register_cipher (&des3_desc); +#endif +#ifdef LTC_CAST5 + register_cipher (&cast5_desc); +#endif +#ifdef LTC_NOEKEON + register_cipher (&noekeon_desc); +#endif +#ifdef LTC_SKIPJACK + register_cipher (&skipjack_desc); +#endif +#ifdef LTC_KHAZAD + register_cipher (&khazad_desc); +#endif +#ifdef LTC_ANUBIS + register_cipher (&anubis_desc); +#endif +#ifdef LTC_KSEED + register_cipher (&kseed_desc); +#endif +#ifdef LTC_KASUMI + register_cipher (&kasumi_desc); +#endif + +#ifdef LTC_TIGER + register_hash (&tiger_desc); +#endif +#ifdef LTC_MD2 + register_hash (&md2_desc); +#endif +#ifdef LTC_MD4 + register_hash (&md4_desc); +#endif +#ifdef LTC_MD5 + register_hash (&md5_desc); +#endif +#ifdef LTC_SHA1 + register_hash (&sha1_desc); +#endif +#ifdef LTC_SHA224 + register_hash (&sha224_desc); +#endif +#ifdef LTC_SHA256 + register_hash (&sha256_desc); +#endif +#ifdef LTC_SHA384 + register_hash (&sha384_desc); +#endif +#ifdef LTC_SHA512 + register_hash (&sha512_desc); +#endif +#ifdef LTC_RIPEMD128 + register_hash (&rmd128_desc); +#endif +#ifdef LTC_RIPEMD160 + register_hash (&rmd160_desc); +#endif +#ifdef LTC_RIPEMD256 + register_hash (&rmd256_desc); +#endif +#ifdef LTC_RIPEMD320 + register_hash (&rmd320_desc); +#endif +#ifdef LTC_WHIRLPOOL + register_hash (&whirlpool_desc); +#endif +#ifdef LTC_CHC_HASH +#error LTC_CHC_HASH is not supported + register_hash(&chc_desc); + if ((err = chc_register(register_cipher(&aes_desc))) != CRYPT_OK) { + fprintf(stderr, "chc_register error: %s\n", + error_to_string(err)); + exit(EXIT_FAILURE); + } +#endif + +#ifndef LTC_NO_PRNGS +#ifndef LTC_YARROW +#error This demo requires Yarrow. +#endif + register_prng(&yarrow_desc); +#ifdef LTC_FORTUNA + register_prng(&fortuna_desc); +#endif +#ifdef LTC_RC4 + register_prng(&rc4_desc); +#endif +#ifdef LTC_SPRNG + register_prng(&sprng_desc); +#endif + + /* + if ((err = rng_make_prng(128, find_prng("yarrow"), + &yarrow_prng, NULL)) != CRYPT_OK) { + fprintf(stderr, "rng_make_prng failed: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + */ +#endif + + register_prng(&prng_mpa_desc); +} + + +/* + * Compute the LibTomCrypt "hashindex" given a TEE Algorithm "algo" + * Return + * - TEE_SUCCESS in case of success, + * - TEE_ERROR_BAD_PARAMETERS in case algo is not a valid algo + * - TEE_ERROR_NOT_SUPPORTED in case algo is not supported by LTC + * Return -1 in case of error + */ +TEE_Result tee_algo_to_ltc_hashindex(uint32_t algo, int *ltc_hashindex) +{ + switch (algo) { + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1: + case TEE_ALG_SHA1: + case TEE_ALG_DSA_SHA1: + case TEE_ALG_HMAC_SHA1: + *ltc_hashindex = find_hash("sha1"); + break; + + case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: + case TEE_ALG_MD5: + case TEE_ALG_HMAC_MD5: + *ltc_hashindex = find_hash("md5"); + break; + + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224: + case TEE_ALG_SHA224: + case TEE_ALG_HMAC_SHA224: + *ltc_hashindex = find_hash("sha224"); + break; + + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256: + case TEE_ALG_SHA256: + case TEE_ALG_HMAC_SHA256: + *ltc_hashindex = find_hash("sha256"); + break; + + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384: + case TEE_ALG_SHA384: + case TEE_ALG_HMAC_SHA384: + *ltc_hashindex = find_hash("sha384"); + break; + + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512: + case TEE_ALG_SHA512: + case TEE_ALG_HMAC_SHA512: + *ltc_hashindex = find_hash("sha512"); + break; + + case TEE_ALG_RSAES_PKCS1_V1_5: + *ltc_hashindex = -1; /* invalid one. but it should not be used anyway */ + return TEE_SUCCESS; + + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + if (*ltc_hashindex < 0) + return TEE_ERROR_NOT_SUPPORTED; + else + return TEE_SUCCESS; +} + +/* + * Compute the LibTomCrypt "cipherindex" given a TEE Algorithm "algo" + * Return + * - TEE_SUCCESS in case of success, + * - TEE_ERROR_BAD_PARAMETERS in case algo is not a valid algo + * - TEE_ERROR_NOT_SUPPORTED in case algo is not supported by LTC + * Return -1 in case of error + */ +TEE_Result tee_algo_to_ltc_cipherindex(uint32_t algo, int *ltc_cipherindex) +{ + switch (algo) { + case TEE_ALG_AES_CBC_MAC_NOPAD: + case TEE_ALG_AES_CBC_MAC_PKCS5: + case TEE_ALG_AES_CMAC: + case TEE_ALG_AES_ECB_NOPAD: + case TEE_ALG_AES_CBC_NOPAD: + case TEE_ALG_AES_CTR: + case TEE_ALG_AES_CTS: + case TEE_ALG_AES_XTS: + case TEE_ALG_AES_CCM: + case TEE_ALG_AES_GCM: + *ltc_cipherindex = find_cipher("aes"); + break; + + case TEE_ALG_DES_CBC_MAC_NOPAD: + case TEE_ALG_DES_CBC_MAC_PKCS5: + case TEE_ALG_DES_ECB_NOPAD: + case TEE_ALG_DES_CBC_NOPAD: + *ltc_cipherindex = find_cipher("des"); + break; + + case TEE_ALG_DES3_CBC_MAC_NOPAD: + case TEE_ALG_DES3_CBC_MAC_PKCS5: + case TEE_ALG_DES3_ECB_NOPAD: + case TEE_ALG_DES3_CBC_NOPAD: + *ltc_cipherindex = find_cipher("3des"); + break; + + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + if (*ltc_cipherindex < 0) + return TEE_ERROR_NOT_SUPPORTED; + else + return TEE_SUCCESS; +} + +void tee_ltc_init(void) +{ + tee_ltc_alloc_mpa(); + tee_ltc_reg_algs(); +} + +void tee_ltc_deinit(void) +{ + tee_ltc_dealloc_mpa(); +} + +/* + * Get the RNG index to use + */ + +int tee_ltc_get_rng_mpa(void) +{ + static int first = 1; + static int lindex = -1; + + if (first) { + lindex = find_prng("prng_mpa"); + first = 0; + } + return lindex; +} diff --git a/core/lib/libtomcrypt/sub.mk b/core/lib/libtomcrypt/sub.mk new file mode 100644 index 00000000000..18938cff225 --- /dev/null +++ b/core/lib/libtomcrypt/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += include + +subdirs-y += src diff --git a/core/lib/libtomcrypt/test/base64_test.c b/core/lib/libtomcrypt/test/base64_test.c new file mode 100644 index 00000000000..af20a6743c6 --- /dev/null +++ b/core/lib/libtomcrypt/test/base64_test.c @@ -0,0 +1,24 @@ +#include + +int base64_test(void) +{ + unsigned char in[64], out[256], tmp[64]; + unsigned long x, l1, l2; + + for (x = 0; x < 64; x++) { + yarrow_read(in, x, &yarrow_prng); + l1 = sizeof(out); + DO(base64_encode(in, x, out, &l1)); + l2 = sizeof(tmp); + DO(base64_decode(out, l1, tmp, &l2)); + if (l2 != x || memcmp(tmp, in, x)) { + fprintf(stderr, "base64 failed %lu %lu %lu", x, l1, l2); + return 1; + } + } + return 0; +} + +/* $Source: /cvs/libtom/libtomcrypt/testprof/base64_test.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2005/05/21 12:51:25 $ */ diff --git a/core/lib/libtomcrypt/test/cipher_hash_test.c b/core/lib/libtomcrypt/test/cipher_hash_test.c new file mode 100644 index 00000000000..27232e28c3c --- /dev/null +++ b/core/lib/libtomcrypt/test/cipher_hash_test.c @@ -0,0 +1,45 @@ +/* test the ciphers and hashes using their built-in self-tests */ + +#include + +int cipher_hash_test(void) +{ + int x; + unsigned char buf[4096]; + unsigned long n; + prng_state nprng; + + /* test ciphers */ + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + DO(cipher_descriptor[x].test()); + } + + /* test hashes */ + for (x = 0; hash_descriptor[x].name != NULL; x++) { + DO(hash_descriptor[x].test()); + } + + /* test prngs (test, import/export */ + for (x = 0; prng_descriptor[x].name != NULL; x++) { + DO(prng_descriptor[x].test()); + DO(prng_descriptor[x].start(&nprng)); + DO(prng_descriptor[x].add_entropy((unsigned char *)"helloworld12", 12, &nprng)); + DO(prng_descriptor[x].ready(&nprng)); + n = sizeof(buf); + DO(prng_descriptor[x].pexport(buf, &n, &nprng)); + prng_descriptor[x].done(&nprng); + DO(prng_descriptor[x].pimport(buf, n, &nprng)); + DO(prng_descriptor[x].ready(&nprng)); + if (prng_descriptor[x].read(buf, 100, &nprng) != 100) { + fprintf(stderr, "Error reading from imported PRNG!\n"); + exit(EXIT_FAILURE); + } + prng_descriptor[x].done(&nprng); + } + + return 0; +} + +/* $Source: /cvs/libtom/libtomcrypt/testprof/cipher_hash_test.c,v $ */ +/* $Revision: 1.3 $ */ +/* $Date: 2005/05/05 14:35:59 $ */ diff --git a/core/lib/libtomcrypt/test/der_tests.c b/core/lib/libtomcrypt/test/der_tests.c new file mode 100644 index 00000000000..2b5a5119cf5 --- /dev/null +++ b/core/lib/libtomcrypt/test/der_tests.c @@ -0,0 +1,854 @@ +#include +#if defined(GMP_LTC_DESC) || defined(USE_GMP) +#include +#endif + +#ifndef LTC_DER + +int der_tests(void) +{ + fprintf(stderr, "NOP"); + return 0; +} + +#else + +static void der_set_test(void) +{ + ltc_asn1_list list[10]; + static const unsigned char oct_str[] = { 1, 2, 3, 4 }; + static const unsigned char bin_str[] = { 1, 0, 0, 1 }; + static const unsigned long int_val = 12345678UL; + + unsigned char strs[10][10], outbuf[128]; + unsigned long x, val, outlen; + int err; + + /* make structure and encode it */ + LTC_SET_ASN1(list, 0, LTC_ASN1_OCTET_STRING, oct_str, sizeof(oct_str)); + LTC_SET_ASN1(list, 1, LTC_ASN1_BIT_STRING, bin_str, sizeof(bin_str)); + LTC_SET_ASN1(list, 2, LTC_ASN1_SHORT_INTEGER, &int_val, 1); + + /* encode it */ + outlen = sizeof(outbuf); + if ((err = der_encode_set(list, 3, outbuf, &outlen)) != CRYPT_OK) { + fprintf(stderr, "error encoding set: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + + + /* first let's test the set_decoder out of order to see what happens, we should get all the fields we expect even though they're in a diff order */ + LTC_SET_ASN1(list, 0, LTC_ASN1_BIT_STRING, strs[1], sizeof(strs[1])); + LTC_SET_ASN1(list, 1, LTC_ASN1_SHORT_INTEGER, &val, 1); + LTC_SET_ASN1(list, 2, LTC_ASN1_OCTET_STRING, strs[0], sizeof(strs[0])); + + if ((err = der_decode_set(outbuf, outlen, list, 3)) != CRYPT_OK) { + fprintf(stderr, "error decoding set using der_decode_set: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + + /* now compare the items */ + if (memcmp(strs[0], oct_str, sizeof(oct_str))) { + fprintf(stderr, "error decoding set using der_decode_set (oct_str is wrong):\n"); + exit(EXIT_FAILURE); + } + + if (memcmp(strs[1], bin_str, sizeof(bin_str))) { + fprintf(stderr, "error decoding set using der_decode_set (bin_str is wrong):\n"); + exit(EXIT_FAILURE); + } + + if (val != int_val) { + fprintf(stderr, "error decoding set using der_decode_set (int_val is wrong):\n"); + exit(EXIT_FAILURE); + } + + strcpy((char*)strs[0], "one"); + strcpy((char*)strs[1], "one2"); + strcpy((char*)strs[2], "two"); + strcpy((char*)strs[3], "aaa"); + strcpy((char*)strs[4], "aaaa"); + strcpy((char*)strs[5], "aab"); + strcpy((char*)strs[6], "aaab"); + strcpy((char*)strs[7], "bbb"); + strcpy((char*)strs[8], "bbba"); + strcpy((char*)strs[9], "bbbb"); + + for (x = 0; x < 10; x++) { + LTC_SET_ASN1(list, x, LTC_ASN1_PRINTABLE_STRING, strs[x], strlen((char*)strs[x])); + } + + outlen = sizeof(outbuf); + if ((err = der_encode_setof(list, 10, outbuf, &outlen)) != CRYPT_OK) { + fprintf(stderr, "error encoding SET OF: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + + for (x = 0; x < 10; x++) { + LTC_SET_ASN1(list, x, LTC_ASN1_PRINTABLE_STRING, strs[x], sizeof(strs[x]) - 1); + } + XMEMSET(strs, 0, sizeof(strs)); + + if ((err = der_decode_set(outbuf, outlen, list, 10)) != CRYPT_OK) { + fprintf(stderr, "error decoding SET OF: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + + /* now compare */ + for (x = 1; x < 10; x++) { + if (!(strlen((char*)strs[x-1]) <= strlen((char*)strs[x])) && strcmp((char*)strs[x-1], (char*)strs[x]) >= 0) { + fprintf(stderr, "error SET OF order at %lu is wrong\n", x); + exit(EXIT_FAILURE); + } + } + +} + + +/* we are encoding + + SEQUENCE { + PRINTABLE "printable" + IA5 "ia5" + SEQUENCE { + INTEGER 12345678 + UTCTIME { 91, 5, 6, 16, 45, 40, 1, 7, 0 } + SEQUENCE { + OCTET STRING { 1, 2, 3, 4 } + BIT STRING { 1, 0, 0, 1 } + SEQUENCE { + OID { 1, 2, 840, 113549 } + NULL + SET OF { + PRINTABLE "333" // WILL GET SORTED + PRINTABLE "222" + } + } + } + } + +*/ + +static void der_flexi_test(void) +{ + static const char printable_str[] = "printable"; + static const char set1_str[] = "333"; + static const char set2_str[] = "222"; + static const char ia5_str[] = "ia5"; + static const unsigned long int_val = 12345678UL; + static const ltc_utctime utctime = { 91, 5, 6, 16, 45, 40, 1, 7, 0 }; + static const unsigned char oct_str[] = { 1, 2, 3, 4 }; + static const unsigned char bit_str[] = { 1, 0, 0, 1 }; + static const unsigned long oid_str[] = { 1, 2, 840, 113549 }; + + unsigned char encode_buf[192]; + unsigned long encode_buf_len, decode_len; + int err; + + ltc_asn1_list static_list[5][3], *decoded_list, *l; + + /* build list */ + LTC_SET_ASN1(static_list[0], 0, LTC_ASN1_PRINTABLE_STRING, (void *)printable_str, strlen(printable_str)); + LTC_SET_ASN1(static_list[0], 1, LTC_ASN1_IA5_STRING, (void *)ia5_str, strlen(ia5_str)); + LTC_SET_ASN1(static_list[0], 2, LTC_ASN1_SEQUENCE, static_list[1], 3); + + LTC_SET_ASN1(static_list[1], 0, LTC_ASN1_SHORT_INTEGER, (void *)&int_val, 1); + LTC_SET_ASN1(static_list[1], 1, LTC_ASN1_UTCTIME, (void *)&utctime, 1); + LTC_SET_ASN1(static_list[1], 2, LTC_ASN1_SEQUENCE, static_list[2], 3); + + LTC_SET_ASN1(static_list[2], 0, LTC_ASN1_OCTET_STRING, (void *)oct_str, 4); + LTC_SET_ASN1(static_list[2], 1, LTC_ASN1_BIT_STRING, (void *)bit_str, 4); + LTC_SET_ASN1(static_list[2], 2, LTC_ASN1_SEQUENCE, static_list[3], 3); + + LTC_SET_ASN1(static_list[3], 0, LTC_ASN1_OBJECT_IDENTIFIER,(void *)oid_str, 4); + LTC_SET_ASN1(static_list[3], 1, LTC_ASN1_NULL, NULL, 0); + LTC_SET_ASN1(static_list[3], 2, LTC_ASN1_SETOF, static_list[4], 2); + + LTC_SET_ASN1(static_list[4], 0, LTC_ASN1_PRINTABLE_STRING, set1_str, strlen(set1_str)); + LTC_SET_ASN1(static_list[4], 1, LTC_ASN1_PRINTABLE_STRING, set2_str, strlen(set2_str)); + + /* encode it */ + encode_buf_len = sizeof(encode_buf); + if ((err = der_encode_sequence(&static_list[0][0], 3, encode_buf, &encode_buf_len)) != CRYPT_OK) { + fprintf(stderr, "Encoding static_list: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + +#if 0 + { + FILE *f; + f = fopen("t.bin", "wb"); + fwrite(encode_buf, 1, encode_buf_len, f); + fclose(f); + } +#endif + + /* decode with flexi */ + decode_len = encode_buf_len; + if ((err = der_decode_sequence_flexi(encode_buf, &decode_len, &decoded_list)) != CRYPT_OK) { + fprintf(stderr, "decoding static_list: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + + if (decode_len != encode_buf_len) { + fprintf(stderr, "Decode len of %lu does not match encode len of %lu \n", decode_len, encode_buf_len); + exit(EXIT_FAILURE); + } + + /* we expect l->next to be NULL and l->child to not be */ + l = decoded_list; + if (l->next != NULL || l->child == NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + /* we expect a SEQUENCE */ + if (l->type != LTC_ASN1_SEQUENCE) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + l = l->child; + + /* PRINTABLE STRING */ + /* we expect printable_str */ + if (l->next == NULL || l->child != NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_PRINTABLE_STRING) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->size != strlen(printable_str) || memcmp(printable_str, l->data, l->size)) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + /* move to next */ + l = l->next; + + /* IA5 STRING */ + /* we expect ia5_str */ + if (l->next == NULL || l->child != NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_IA5_STRING) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->size != strlen(ia5_str) || memcmp(ia5_str, l->data, l->size)) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + /* move to next */ + l = l->next; + + /* expect child anve move down */ + + if (l->next != NULL || l->child == NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_SEQUENCE) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + l = l->child; + + + /* INTEGER */ + + if (l->next == NULL || l->child != NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_INTEGER) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (mp_cmp_d(l->data, 12345678UL) != LTC_MP_EQ) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + /* move to next */ + l = l->next; + + /* UTCTIME */ + + if (l->next == NULL || l->child != NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_UTCTIME) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (memcmp(l->data, &utctime, sizeof(utctime))) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + /* move to next */ + l = l->next; + + /* expect child anve move down */ + + if (l->next != NULL || l->child == NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_SEQUENCE) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + l = l->child; + + + /* OCTET STRING */ + /* we expect oct_str */ + if (l->next == NULL || l->child != NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_OCTET_STRING) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->size != sizeof(oct_str) || memcmp(oct_str, l->data, l->size)) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + /* move to next */ + l = l->next; + + /* BIT STRING */ + /* we expect oct_str */ + if (l->next == NULL || l->child != NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_BIT_STRING) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->size != sizeof(bit_str) || memcmp(bit_str, l->data, l->size)) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + /* move to next */ + l = l->next; + + /* expect child anve move down */ + + if (l->next != NULL || l->child == NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_SEQUENCE) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + l = l->child; + + + /* OID STRING */ + /* we expect oid_str */ + if (l->next == NULL || l->child != NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_OBJECT_IDENTIFIER) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->size != sizeof(oid_str)/sizeof(oid_str[0]) || memcmp(oid_str, l->data, l->size*sizeof(oid_str[0]))) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + /* move to next */ + l = l->next; + + /* NULL */ + if (l->type != LTC_ASN1_NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + /* move to next */ + l = l->next; + + /* expect child anve move down */ + if (l->next != NULL || l->child == NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_SET) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + l = l->child; + + /* PRINTABLE STRING */ + /* we expect printable_str */ + if (l->next == NULL || l->child != NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_PRINTABLE_STRING) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + +/* note we compare set2_str FIRST because the SET OF is sorted and "222" comes before "333" */ + if (l->size != strlen(set2_str) || memcmp(set2_str, l->data, l->size)) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + /* move to next */ + l = l->next; + + /* PRINTABLE STRING */ + /* we expect printable_str */ + if (l->type != LTC_ASN1_PRINTABLE_STRING) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->size != strlen(set1_str) || memcmp(set1_str, l->data, l->size)) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + + der_sequence_free(l); + +} + +static int der_choice_test(void) +{ + ltc_asn1_list types[7], host[1]; + unsigned char bitbuf[10], octetbuf[10], ia5buf[10], printbuf[10], outbuf[256]; + unsigned long integer, oidbuf[10], outlen, inlen, x, y; + void *mpinteger; + ltc_utctime utctime = { 91, 5, 6, 16, 45, 40, 1, 7, 0 }; + + /* setup variables */ + for (x = 0; x < sizeof(bitbuf); x++) { bitbuf[x] = x & 1; } + for (x = 0; x < sizeof(octetbuf); x++) { octetbuf[x] = x; } + for (x = 0; x < sizeof(ia5buf); x++) { ia5buf[x] = 'a'; } + for (x = 0; x < sizeof(printbuf); x++) { printbuf[x] = 'a'; } + integer = 1; + for (x = 0; x < sizeof(oidbuf)/sizeof(oidbuf[0]); x++) { oidbuf[x] = x + 1; } + DO(mp_init(&mpinteger)); + + for (x = 0; x < 14; x++) { + /* setup list */ + LTC_SET_ASN1(types, 0, LTC_ASN1_PRINTABLE_STRING, printbuf, sizeof(printbuf)); + LTC_SET_ASN1(types, 1, LTC_ASN1_BIT_STRING, bitbuf, sizeof(bitbuf)); + LTC_SET_ASN1(types, 2, LTC_ASN1_OCTET_STRING, octetbuf, sizeof(octetbuf)); + LTC_SET_ASN1(types, 3, LTC_ASN1_IA5_STRING, ia5buf, sizeof(ia5buf)); + if (x > 7) { + LTC_SET_ASN1(types, 4, LTC_ASN1_SHORT_INTEGER, &integer, 1); + } else { + LTC_SET_ASN1(types, 4, LTC_ASN1_INTEGER, mpinteger, 1); + } + LTC_SET_ASN1(types, 5, LTC_ASN1_OBJECT_IDENTIFIER, oidbuf, sizeof(oidbuf)/sizeof(oidbuf[0])); + LTC_SET_ASN1(types, 6, LTC_ASN1_UTCTIME, &utctime, 1); + + LTC_SET_ASN1(host, 0, LTC_ASN1_CHOICE, types, 7); + + + /* encode */ + outlen = sizeof(outbuf); + DO(der_encode_sequence(&types[x>6?x-7:x], 1, outbuf, &outlen)); + + /* decode it */ + inlen = outlen; + DO(der_decode_sequence(outbuf, inlen, &host[0], 1)); + + for (y = 0; y < 7; y++) { + if (types[y].used && y != (x>6?x-7:x)) { + fprintf(stderr, "CHOICE, flag %lu in trial %lu was incorrectly set to one\n", y, x); + return 1; + } + if (!types[y].used && y == (x>6?x-7:x)) { + fprintf(stderr, "CHOICE, flag %lu in trial %lu was incorrectly set to zero\n", y, x); + return 1; + } + } + } + mp_clear(mpinteger); + return 0; +} + +#define MAX_OCTET_LENGTH 256 + +int der_tests(void) +{ + unsigned long x, y, z, zz, oid[2][32]; + unsigned char buf[3][2048]; + void *a, *b, *c, *d, *e, *f, *g; + + static const unsigned char rsa_oid_der[] = { 0x06, 0x06, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d }; + static const unsigned long rsa_oid[] = { 1, 2, 840, 113549 }; + + static const unsigned char rsa_ia5[] = "test1@rsa.com"; + static const unsigned char rsa_ia5_der[] = { 0x16, 0x0d, 0x74, 0x65, 0x73, 0x74, 0x31, + 0x40, 0x72, 0x73, 0x61, 0x2e, 0x63, 0x6f, 0x6d }; + + static const unsigned char rsa_printable[] = "Test User 1"; + static const unsigned char rsa_printable_der[] = { 0x13, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, + 0x73, 0x65, 0x72, 0x20, 0x31 }; + + static const ltc_utctime rsa_time1 = { 91, 5, 6, 16, 45, 40, 1, 7, 0 }; + static const ltc_utctime rsa_time2 = { 91, 5, 6, 23, 45, 40, 0, 0, 0 }; + ltc_utctime tmp_time; + + static const unsigned char rsa_time1_der[] = { 0x17, 0x11, 0x39, 0x31, 0x30, 0x35, 0x30, 0x36, 0x31, 0x36, 0x34, 0x35, 0x34, 0x30, 0x2D, 0x30, 0x37, 0x30, 0x30 }; + static const unsigned char rsa_time2_der[] = { 0x17, 0x0d, 0x39, 0x31, 0x30, 0x35, 0x30, 0x36, 0x32, 0x33, 0x34, 0x35, 0x34, 0x30, 0x5a }; + + static const wchar_t utf8_1[] = { 0x0041, 0x2262, 0x0391, 0x002E }; + static const unsigned char utf8_1_der[] = { 0x0C, 0x07, 0x41, 0xE2, 0x89, 0xA2, 0xCE, 0x91, 0x2E }; + static const wchar_t utf8_2[] = { 0xD55C, 0xAD6D, 0xC5B4 }; + static const unsigned char utf8_2_der[] = { 0x0C, 0x09, 0xED, 0x95, 0x9C, 0xEA, 0xB5, 0xAD, 0xEC, 0x96, 0xB4 }; + + unsigned char utf8_buf[32]; + wchar_t utf8_out[32]; + + DO(mp_init_multi(&a, &b, &c, &d, &e, &f, &g, NULL)); + for (zz = 0; zz < 16; zz++) { +#ifdef USE_TFM + for (z = 0; z < 256; z++) { +#else + for (z = 0; z < (MAX_OCTET_LENGTH >> 1); z++) { +#endif + if (yarrow_read(buf[0], z, &yarrow_prng) != z) { + fprintf(stderr, "Failed to read %lu bytes from yarrow\n", z); + return 1; + } + DO(mp_read_unsigned_bin(a, buf[0], z)); +/* if (mp_iszero(a) == LTC_MP_NO) { a.sign = buf[0][0] & 1 ? LTC_MP_ZPOS : LTC_MP_NEG; } */ + x = sizeof(buf[0]); + DO(der_encode_integer(a, buf[0], &x)); + DO(der_length_integer(a, &y)); + if (y != x) { fprintf(stderr, "DER INTEGER size mismatch\n"); return 1; } + mp_set_int(b, 0); + DO(der_decode_integer(buf[0], y, b)); + if (y != x || mp_cmp(a, b) != LTC_MP_EQ) { + fprintf(stderr, "%lu: %lu vs %lu\n", z, x, y); + mp_clear_multi(a, b, c, d, e, f, g, NULL); + return 1; + } + } + } + +/* test short integer */ + for (zz = 0; zz < 256; zz++) { + for (z = 1; z < 4; z++) { + if (yarrow_read(buf[0], z, &yarrow_prng) != z) { + fprintf(stderr, "Failed to read %lu bytes from yarrow\n", z); + return 1; + } + /* encode with normal */ + DO(mp_read_unsigned_bin(a, buf[0], z)); + + x = sizeof(buf[0]); + DO(der_encode_integer(a, buf[0], &x)); + + /* encode with short */ + y = sizeof(buf[1]); + DO(der_encode_short_integer(mp_get_int(a), buf[1], &y)); + if (x != y || memcmp(buf[0], buf[1], x)) { + fprintf(stderr, "DER INTEGER short encoding failed, %lu, %lu\n", x, y); + for (z = 0; z < x; z++) fprintf(stderr, "%02x ", buf[0][z]); fprintf(stderr, "\n"); + for (z = 0; z < y; z++) fprintf(stderr, "%02x ", buf[1][z]); fprintf(stderr, "\n"); + mp_clear_multi(a, b, c, d, e, f, g, NULL); + return 1; + } + + /* decode it */ + x = 0; + DO(der_decode_short_integer(buf[1], y, &x)); + if (x != mp_get_int(a)) { + fprintf(stderr, "DER INTEGER short decoding failed, %lu, %lu\n", x, mp_get_int(a)); + mp_clear_multi(a, b, c, d, e, f, g, NULL); + return 1; + } + } + } + mp_clear_multi(a, b, c, d, e, f, g, NULL); + + +/* Test bit string */ + for (zz = 1; zz < 1536; zz++) { + yarrow_read(buf[0], zz, &yarrow_prng); + for (z = 0; z < zz; z++) { + buf[0][z] &= 0x01; + } + x = sizeof(buf[1]); + DO(der_encode_bit_string(buf[0], zz, buf[1], &x)); + DO(der_length_bit_string(zz, &y)); + if (y != x) { + fprintf(stderr, "\nDER BIT STRING length of encoded not match expected : %lu, %lu, %lu\n", z, x, y); + return 1; + } + + y = sizeof(buf[2]); + DO(der_decode_bit_string(buf[1], x, buf[2], &y)); + if (y != zz || memcmp(buf[0], buf[2], zz)) { + fprintf(stderr, "%lu, %lu, %d\n", y, zz, memcmp(buf[0], buf[2], zz)); + return 1; + } + } + +/* Test octet string */ + for (zz = 1; zz < 1536; zz++) { + yarrow_read(buf[0], zz, &yarrow_prng); + x = sizeof(buf[1]); + DO(der_encode_octet_string(buf[0], zz, buf[1], &x)); + DO(der_length_octet_string(zz, &y)); + if (y != x) { + fprintf(stderr, "\nDER OCTET STRING length of encoded not match expected : %lu, %lu, %lu\n", z, x, y); + return 1; + } + y = sizeof(buf[2]); + DO(der_decode_octet_string(buf[1], x, buf[2], &y)); + if (y != zz || memcmp(buf[0], buf[2], zz)) { + fprintf(stderr, "%lu, %lu, %d\n", y, zz, memcmp(buf[0], buf[2], zz)); + return 1; + } + } + +/* test OID */ + x = sizeof(buf[0]); + DO(der_encode_object_identifier((unsigned long*)rsa_oid, sizeof(rsa_oid)/sizeof(rsa_oid[0]), buf[0], &x)); + if (x != sizeof(rsa_oid_der) || memcmp(rsa_oid_der, buf[0], x)) { + fprintf(stderr, "rsa_oid_der encode failed to match, %lu, ", x); + for (y = 0; y < x; y++) fprintf(stderr, "%02x ", buf[0][y]); + fprintf(stderr, "\n"); + return 1; + } + + y = sizeof(oid[0])/sizeof(oid[0][0]); + DO(der_decode_object_identifier(buf[0], x, oid[0], &y)); + if (y != sizeof(rsa_oid)/sizeof(rsa_oid[0]) || memcmp(rsa_oid, oid[0], sizeof(rsa_oid))) { + fprintf(stderr, "rsa_oid_der decode failed to match, %lu, ", y); + for (z = 0; z < y; z++) fprintf(stderr, "%lu ", oid[0][z]); + fprintf(stderr, "\n"); + return 1; + } + + /* do random strings */ + for (zz = 0; zz < 5000; zz++) { + /* pick a random number of words */ + yarrow_read(buf[0], 4, &yarrow_prng); + LOAD32L(z, buf[0]); + z = 2 + (z % ((sizeof(oid[0])/sizeof(oid[0][0])) - 2)); + + /* fill them in */ + oid[0][0] = buf[0][0] % 3; + oid[0][1] = buf[0][1] % 40; + + for (y = 2; y < z; y++) { + yarrow_read(buf[0], 4, &yarrow_prng); + LOAD32L(oid[0][y], buf[0]); + } + + /* encode it */ + x = sizeof(buf[0]); + DO(der_encode_object_identifier(oid[0], z, buf[0], &x)); + DO(der_length_object_identifier(oid[0], z, &y)); + if (x != y) { + fprintf(stderr, "Random OID %lu test failed, length mismatch: %lu, %lu\n", z, x, y); + for (x = 0; x < z; x++) fprintf(stderr, "%lu\n", oid[0][x]); + return 1; + } + + /* decode it */ + y = sizeof(oid[0])/sizeof(oid[0][0]); + DO(der_decode_object_identifier(buf[0], x, oid[1], &y)); + if (y != z) { + fprintf(stderr, "Random OID %lu test failed, decode length mismatch: %lu, %lu\n", z, x, y); + return 1; + } + if (memcmp(oid[0], oid[1], sizeof(oid[0][0]) * z)) { + fprintf(stderr, "Random OID %lu test failed, decoded values wrong\n", z); + for (x = 0; x < z; x++) fprintf(stderr, "%lu\n", oid[0][x]); fprintf(stderr, "\n\n Got \n\n"); + for (x = 0; x < z; x++) fprintf(stderr, "%lu\n", oid[1][x]); + return 1; + } + } + +/* IA5 string */ + x = sizeof(buf[0]); + DO(der_encode_ia5_string(rsa_ia5, strlen((char*)rsa_ia5), buf[0], &x)); + if (x != sizeof(rsa_ia5_der) || memcmp(buf[0], rsa_ia5_der, x)) { + fprintf(stderr, "IA5 encode failed: %lu, %lu\n", x, (unsigned long)sizeof(rsa_ia5_der)); + return 1; + } + DO(der_length_ia5_string(rsa_ia5, strlen((char*)rsa_ia5), &y)); + if (y != x) { + fprintf(stderr, "IA5 length failed to match: %lu, %lu\n", x, y); + return 1; + } + y = sizeof(buf[1]); + DO(der_decode_ia5_string(buf[0], x, buf[1], &y)); + if (y != strlen((char*)rsa_ia5) || memcmp(buf[1], rsa_ia5, strlen((char*)rsa_ia5))) { + fprintf(stderr, "DER IA5 failed test vector\n"); + return 1; + } + +/* Printable string */ + x = sizeof(buf[0]); + DO(der_encode_printable_string(rsa_printable, strlen((char*)rsa_printable), buf[0], &x)); + if (x != sizeof(rsa_printable_der) || memcmp(buf[0], rsa_printable_der, x)) { + fprintf(stderr, "PRINTABLE encode failed: %lu, %lu\n", x, (unsigned long)sizeof(rsa_printable_der)); + return 1; + } + DO(der_length_printable_string(rsa_printable, strlen((char*)rsa_printable), &y)); + if (y != x) { + fprintf(stderr, "printable length failed to match: %lu, %lu\n", x, y); + return 1; + } + y = sizeof(buf[1]); + DO(der_decode_printable_string(buf[0], x, buf[1], &y)); + if (y != strlen((char*)rsa_printable) || memcmp(buf[1], rsa_printable, strlen((char*)rsa_printable))) { + fprintf(stderr, "DER printable failed test vector\n"); + return 1; + } + +/* Test UTC time */ + x = sizeof(buf[0]); + DO(der_encode_utctime((ltc_utctime*)&rsa_time1, buf[0], &x)); + if (x != sizeof(rsa_time1_der) || memcmp(buf[0], rsa_time1_der, x)) { + fprintf(stderr, "UTCTIME encode of rsa_time1 failed: %lu, %lu\n", x, (unsigned long)sizeof(rsa_time1_der)); +fprintf(stderr, "\n\n"); +for (y = 0; y < x; y++) fprintf(stderr, "%02x ", buf[0][y]); printf("\n"); + + return 1; + } + DO(der_length_utctime((ltc_utctime*)&rsa_time1, &y)); + if (y != x) { + fprintf(stderr, "UTCTIME length failed to match for rsa_time1: %lu, %lu\n", x, y); + return 1; + } + DO(der_decode_utctime(buf[0], &y, &tmp_time)); + if (y != x || memcmp(&rsa_time1, &tmp_time, sizeof(ltc_utctime))) { + fprintf(stderr, "UTCTIME decode failed for rsa_time1: %lu %lu\n", x, y); +fprintf(stderr, "\n\n%u %u %u %u %u %u %u %u %u\n\n", +tmp_time.YY, +tmp_time.MM, +tmp_time.DD, +tmp_time.hh, +tmp_time.mm, +tmp_time.ss, +tmp_time.off_dir, +tmp_time.off_mm, +tmp_time.off_hh); + return 1; + } + + x = sizeof(buf[0]); + DO(der_encode_utctime((ltc_utctime*)&rsa_time2, buf[0], &x)); + if (x != sizeof(rsa_time2_der) || memcmp(buf[0], rsa_time2_der, x)) { + fprintf(stderr, "UTCTIME encode of rsa_time2 failed: %lu, %lu\n", x, (unsigned long)sizeof(rsa_time1_der)); +fprintf(stderr, "\n\n"); +for (y = 0; y < x; y++) fprintf(stderr, "%02x ", buf[0][y]); printf("\n"); + + return 1; + } + DO(der_length_utctime((ltc_utctime*)&rsa_time2, &y)); + if (y != x) { + fprintf(stderr, "UTCTIME length failed to match for rsa_time2: %lu, %lu\n", x, y); + return 1; + } + DO(der_decode_utctime(buf[0], &y, &tmp_time)); + if (y != x || memcmp(&rsa_time2, &tmp_time, sizeof(ltc_utctime))) { + fprintf(stderr, "UTCTIME decode failed for rsa_time2: %lu %lu\n", x, y); +fprintf(stderr, "\n\n%u %u %u %u %u %u %u %u %u\n\n", +tmp_time.YY, +tmp_time.MM, +tmp_time.DD, +tmp_time.hh, +tmp_time.mm, +tmp_time.ss, +tmp_time.off_dir, +tmp_time.off_mm, +tmp_time.off_hh); + + + return 1; + } + + /* UTF 8 */ + /* encode it */ + x = sizeof(utf8_buf); + DO(der_encode_utf8_string(utf8_1, sizeof(utf8_1) / sizeof(utf8_1[0]), utf8_buf, &x)); + if (x != sizeof(utf8_1_der) || memcmp(utf8_buf, utf8_1_der, x)) { + fprintf(stderr, "DER UTF8_1 encoded to %lu bytes\n", x); + for (y = 0; y < x; y++) fprintf(stderr, "%02x ", (unsigned)utf8_buf[y]); fprintf(stderr, "\n"); + return 1; + } + /* decode it */ + y = sizeof(utf8_out) / sizeof(utf8_out[0]); + DO(der_decode_utf8_string(utf8_buf, x, utf8_out, &y)); + if (y != (sizeof(utf8_1) / sizeof(utf8_1[0])) || memcmp(utf8_1, utf8_out, y * sizeof(wchar_t))) { + fprintf(stderr, "DER UTF8_1 decoded to %lu wchar_t\n", y); + for (x = 0; x < y; x++) fprintf(stderr, "%04lx ", (unsigned long)utf8_out[x]); fprintf(stderr, "\n"); + return 1; + } + + /* encode it */ + x = sizeof(utf8_buf); + DO(der_encode_utf8_string(utf8_2, sizeof(utf8_2) / sizeof(utf8_2[0]), utf8_buf, &x)); + if (x != sizeof(utf8_2_der) || memcmp(utf8_buf, utf8_2_der, x)) { + fprintf(stderr, "DER UTF8_2 encoded to %lu bytes\n", x); + for (y = 0; y < x; y++) fprintf(stderr, "%02x ", (unsigned)utf8_buf[y]); fprintf(stderr, "\n"); + return 1; + } + /* decode it */ + y = sizeof(utf8_out) / sizeof(utf8_out[0]); + DO(der_decode_utf8_string(utf8_buf, x, utf8_out, &y)); + if (y != (sizeof(utf8_2) / sizeof(utf8_2[0])) || memcmp(utf8_2, utf8_out, y * sizeof(wchar_t))) { + fprintf(stderr, "DER UTF8_2 decoded to %lu wchar_t\n", y); + for (x = 0; x < y; x++) fprintf(stderr, "%04lx ", (unsigned long)utf8_out[x]); fprintf(stderr, "\n"); + return 1; + } + + + der_set_test(); + der_flexi_test(); + return der_choice_test(); +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/testprof/der_tests.c,v $ */ +/* $Revision: 1.50 $ */ +/* $Date: 2007/05/12 14:20:27 $ */ diff --git a/core/lib/libtomcrypt/test/dsa_test.c b/core/lib/libtomcrypt/test/dsa_test.c new file mode 100644 index 00000000000..bb017a083f0 --- /dev/null +++ b/core/lib/libtomcrypt/test/dsa_test.c @@ -0,0 +1,82 @@ +#include + +#ifdef LTC_MDSA + +int dsa_test(void) +{ + unsigned char msg[16], out[1024], out2[1024]; + unsigned long x, y; + int stat1, stat2; + dsa_key key, key2; + + /* make a random key */ + DO(dsa_make_key(&yarrow_prng, find_prng("yarrow"), 20, 128, &key)); + + /* verify it */ + DO(dsa_verify_key(&key, &stat1)); + if (stat1 == 0) { fprintf(stderr, "dsa_verify_key "); return 1; } + + /* encrypt a message */ + for (x = 0; x < 16; x++) { msg[x] = x; } + x = sizeof(out); + DO(dsa_encrypt_key(msg, 16, out, &x, &yarrow_prng, find_prng("yarrow"), find_hash("sha1"), &key)); + + /* decrypt */ + y = sizeof(out2); + DO(dsa_decrypt_key(out, x, out2, &y, &key)); + + if (y != 16 || memcmp(out2, msg, 16)) { + fprintf(stderr, "dsa_decrypt failed, y == %lu\n", y); + return 1; + } + + /* sign the message */ + x = sizeof(out); + DO(dsa_sign_hash(msg, sizeof(msg), out, &x, &yarrow_prng, find_prng("yarrow"), &key)); + + /* verify it once */ + DO(dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key)); + + /* Modify and verify again */ + msg[0] ^= 1; + DO(dsa_verify_hash(out, x, msg, sizeof(msg), &stat2, &key)); + msg[0] ^= 1; + if (!(stat1 == 1 && stat2 == 0)) { fprintf(stderr, "dsa_verify %d %d", stat1, stat2); return 1; } + + /* test exporting it */ + x = sizeof(out2); + DO(dsa_export(out2, &x, PK_PRIVATE, &key)); + DO(dsa_import(out2, x, &key2)); + + /* verify a signature with it */ + DO(dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key2)); + if (stat1 == 0) { fprintf(stderr, "dsa_verify (import private) %d ", stat1); return 1; } + dsa_free(&key2); + + /* export as public now */ + x = sizeof(out2); + DO(dsa_export(out2, &x, PK_PUBLIC, &key)); + + DO(dsa_import(out2, x, &key2)); + /* verify a signature with it */ + DO(dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key2)); + if (stat1 == 0) { fprintf(stderr, "dsa_verify (import public) %d ", stat1); return 1; } + dsa_free(&key2); + dsa_free(&key); + + return 0; +} + +#else + +int dsa_test(void) +{ + fprintf(stderr, "NOP"); + return 0; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/testprof/dsa_test.c,v $ */ +/* $Revision: 1.10 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/test/ecc_test.c b/core/lib/libtomcrypt/test/ecc_test.c new file mode 100644 index 00000000000..bb3df14fb34 --- /dev/null +++ b/core/lib/libtomcrypt/test/ecc_test.c @@ -0,0 +1,252 @@ +#include + +#ifdef LTC_MECC + +static int sizes[] = { +#ifdef ECC112 +14, +#endif +#ifdef ECC128 +16, +#endif +#ifdef ECC160 +20, +#endif +#ifdef ECC192 +24, +#endif +#ifdef ECC224 +28, +#endif +#ifdef ECC256 +32, +#endif +#ifdef ECC384 +48, +#endif +#ifdef ECC521 +65 +#endif +}; + +#ifdef LTC_ECC_SHAMIR +int ecc_test_shamir(void) +{ + void *modulus, *mp, *kA, *kB, *rA, *rB; + ecc_point *G, *A, *B, *C1, *C2; + int x, y, z; + unsigned char buf[ECC_BUF_SIZE]; + + DO(mp_init_multi(&kA, &kB, &rA, &rB, &modulus, NULL)); + LTC_ARGCHK((G = ltc_ecc_new_point()) != NULL); + LTC_ARGCHK((A = ltc_ecc_new_point()) != NULL); + LTC_ARGCHK((B = ltc_ecc_new_point()) != NULL); + LTC_ARGCHK((C1 = ltc_ecc_new_point()) != NULL); + LTC_ARGCHK((C2 = ltc_ecc_new_point()) != NULL); + + for (x = 0; x < (int)(sizeof(sizes)/sizeof(sizes[0])); x++) { + /* get the base point */ + for (z = 0; ltc_ecc_sets[z].name; z++) { + if (sizes[z] < ltc_ecc_sets[z].size) break; + } + LTC_ARGCHK(ltc_ecc_sets[z].name != NULL); + + /* load it */ + DO(mp_read_radix(G->x, ltc_ecc_sets[z].Gx, 16)); + DO(mp_read_radix(G->y, ltc_ecc_sets[z].Gy, 16)); + DO(mp_set(G->z, 1)); + DO(mp_read_radix(modulus, ltc_ecc_sets[z].prime, 16)); + DO(mp_montgomery_setup(modulus, &mp)); + + /* do 100 random tests */ + for (y = 0; y < 100; y++) { + /* pick a random r1, r2 */ + LTC_ARGCHK(yarrow_read(buf, sizes[x], &yarrow_prng) == sizes[x]); + DO(mp_read_unsigned_bin(rA, buf, sizes[x])); + LTC_ARGCHK(yarrow_read(buf, sizes[x], &yarrow_prng) == sizes[x]); + DO(mp_read_unsigned_bin(rB, buf, sizes[x])); + + /* compute rA * G = A */ + DO(ltc_mp.ecc_ptmul(rA, G, A, modulus, 1)); + + /* compute rB * G = B */ + DO(ltc_mp.ecc_ptmul(rB, G, B, modulus, 1)); + + /* pick a random kA, kB */ + LTC_ARGCHK(yarrow_read(buf, sizes[x], &yarrow_prng) == sizes[x]); + DO(mp_read_unsigned_bin(kA, buf, sizes[x])); + LTC_ARGCHK(yarrow_read(buf, sizes[x], &yarrow_prng) == sizes[x]); + DO(mp_read_unsigned_bin(kB, buf, sizes[x])); + + /* now, compute kA*A + kB*B = C1 using the older method */ + DO(ltc_mp.ecc_ptmul(kA, A, C1, modulus, 0)); + DO(ltc_mp.ecc_ptmul(kB, B, C2, modulus, 0)); + DO(ltc_mp.ecc_ptadd(C1, C2, C1, modulus, mp)); + DO(ltc_mp.ecc_map(C1, modulus, mp)); + + /* now compute using mul2add */ + DO(ltc_mp.ecc_mul2add(A, kA, B, kB, C2, modulus)); + + /* is they the sames? */ + if ((mp_cmp(C1->x, C2->x) != LTC_MP_EQ) || (mp_cmp(C1->y, C2->y) != LTC_MP_EQ) || (mp_cmp(C1->z, C2->z) != LTC_MP_EQ)) { + fprintf(stderr, "ECC failed shamir test: size=%d, testno=%d\n", sizes[x], y); + return 1; + } + } + mp_montgomery_free(mp); + } + ltc_ecc_del_point(C2); + ltc_ecc_del_point(C1); + ltc_ecc_del_point(B); + ltc_ecc_del_point(A); + ltc_ecc_del_point(G); + mp_clear_multi(kA, kB, rA, rB, modulus, NULL); + return 0; +} +#endif + +int ecc_tests (void) +{ + unsigned char buf[4][4096]; + unsigned long x, y, z, s; + int stat, stat2; + ecc_key usera, userb, pubKey, privKey; + + DO(ecc_test ()); + DO(ecc_test ()); + DO(ecc_test ()); + DO(ecc_test ()); + DO(ecc_test ()); + + for (s = 0; s < (sizeof(sizes)/sizeof(sizes[0])); s++) { + /* make up two keys */ + DO(ecc_make_key (&yarrow_prng, find_prng ("yarrow"), sizes[s], &usera)); + DO(ecc_make_key (&yarrow_prng, find_prng ("yarrow"), sizes[s], &userb)); + + /* make the shared secret */ + x = sizeof(buf[0]); + DO(ecc_shared_secret (&usera, &userb, buf[0], &x)); + + y = sizeof(buf[1]); + DO(ecc_shared_secret (&userb, &usera, buf[1], &y)); + + if (y != x) { + fprintf(stderr, "ecc Shared keys are not same size."); + return 1; + } + + if (memcmp (buf[0], buf[1], x)) { + fprintf(stderr, "ecc Shared keys not same contents."); + return 1; + } + + /* now export userb */ + y = sizeof(buf[0]); + DO(ecc_export (buf[1], &y, PK_PUBLIC, &userb)); + ecc_free (&userb); + + /* import and make the shared secret again */ + DO(ecc_import (buf[1], y, &userb)); + + z = sizeof(buf[0]); + DO(ecc_shared_secret (&usera, &userb, buf[2], &z)); + + if (z != x) { + fprintf(stderr, "failed. Size don't match?"); + return 1; + } + if (memcmp (buf[0], buf[2], x)) { + fprintf(stderr, "Failed. Contents didn't match."); + return 1; + } + + /* export with ANSI X9.63 */ + y = sizeof(buf[1]); + DO(ecc_ansi_x963_export(&userb, buf[1], &y)); + ecc_free (&userb); + + /* now import the ANSI key */ + DO(ecc_ansi_x963_import(buf[1], y, &userb)); + + /* shared secret */ + z = sizeof(buf[0]); + DO(ecc_shared_secret (&usera, &userb, buf[2], &z)); + + if (z != x) { + fprintf(stderr, "failed. Size don't match?"); + return 1; + } + if (memcmp (buf[0], buf[2], x)) { + fprintf(stderr, "Failed. Contents didn't match."); + return 1; + } + + ecc_free (&usera); + ecc_free (&userb); + + /* test encrypt_key */ + DO(ecc_make_key (&yarrow_prng, find_prng ("yarrow"), sizes[s], &usera)); + + /* export key */ + x = sizeof(buf[0]); + DO(ecc_export(buf[0], &x, PK_PUBLIC, &usera)); + DO(ecc_import(buf[0], x, &pubKey)); + x = sizeof(buf[0]); + DO(ecc_export(buf[0], &x, PK_PRIVATE, &usera)); + DO(ecc_import(buf[0], x, &privKey)); + + for (x = 0; x < 32; x++) { + buf[0][x] = x; + } + y = sizeof (buf[1]); + DO(ecc_encrypt_key (buf[0], 32, buf[1], &y, &yarrow_prng, find_prng ("yarrow"), find_hash ("sha256"), &pubKey)); + zeromem (buf[0], sizeof (buf[0])); + x = sizeof (buf[0]); + DO(ecc_decrypt_key (buf[1], y, buf[0], &x, &privKey)); + if (x != 32) { + fprintf(stderr, "Failed (length)"); + return 1; + } + for (x = 0; x < 32; x++) { + if (buf[0][x] != x) { + fprintf(stderr, "Failed (contents)"); + return 1; + } + } + /* test sign_hash */ + for (x = 0; x < 16; x++) { + buf[0][x] = x; + } + x = sizeof (buf[1]); + DO(ecc_sign_hash (buf[0], 16, buf[1], &x, &yarrow_prng, find_prng ("yarrow"), &privKey)); + DO(ecc_verify_hash (buf[1], x, buf[0], 16, &stat, &pubKey)); + buf[0][0] ^= 1; + DO(ecc_verify_hash (buf[1], x, buf[0], 16, &stat2, &privKey)); + if (!(stat == 1 && stat2 == 0)) { + fprintf(stderr, "ecc_verify_hash failed %d, %d, ", stat, stat2); + return 1; + } + ecc_free (&usera); + ecc_free (&pubKey); + ecc_free (&privKey); + } +#ifdef LTC_ECC_SHAMIR + return ecc_test_shamir(); +#else + return 0; +#endif +} + +#else + +int ecc_tests(void) +{ + fprintf(stderr, "NOP"); + return 0; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/testprof/ecc_test.c,v $ */ +/* $Revision: 1.22 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/test/mac_test.c b/core/lib/libtomcrypt/test/mac_test.c new file mode 100644 index 00000000000..d0476d7725d --- /dev/null +++ b/core/lib/libtomcrypt/test/mac_test.c @@ -0,0 +1,41 @@ +/* test pmac/omac/hmac */ +#include + +int mac_test(void) +{ +#ifdef LTC_HMAC + DO(hmac_test()); +#endif +#ifdef LTC_PMAC + DO(pmac_test()); +#endif +#ifdef LTC_OMAC + DO(omac_test()); +#endif +#ifdef LTC_XCBC + DO(xcbc_test()); +#endif +#ifdef LTC_F9_MODE + DO(f9_test()); +#endif +#ifdef LTC_EAX_MODE + DO(eax_test()); +#endif +#ifdef LTC_OCB_MODE + DO(ocb_test()); +#endif +#ifdef LTC_CCM_MODE + DO(ccm_test()); +#endif +#ifdef LTC_GCM_MODE + DO(gcm_test()); +#endif +#ifdef LTC_PELICAN + DO(pelican_test()); +#endif + return 0; +} + +/* $Source: /cvs/libtom/libtomcrypt/testprof/mac_test.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/test/modes_test.c b/core/lib/libtomcrypt/test/modes_test.c new file mode 100644 index 00000000000..b9bffafa294 --- /dev/null +++ b/core/lib/libtomcrypt/test/modes_test.c @@ -0,0 +1,119 @@ +/* test CFB/OFB/CBC modes */ +#include + +int modes_test(void) +{ + unsigned char pt[64], ct[64], tmp[64], key[16], iv[16], iv2[16]; + int cipher_idx; +#ifdef LTC_CBC_MODE + symmetric_CBC cbc; +#endif +#ifdef LTC_CFB_MODE + symmetric_CFB cfb; +#endif +#ifdef LTC_OFB_MODE + symmetric_OFB ofb; +#endif + unsigned long l; + + /* make a random pt, key and iv */ + yarrow_read(pt, 64, &yarrow_prng); + yarrow_read(key, 16, &yarrow_prng); + yarrow_read(iv, 16, &yarrow_prng); + + /* get idx of AES handy */ + cipher_idx = find_cipher("aes"); + if (cipher_idx == -1) { + fprintf(stderr, "test requires AES"); + return 1; + } + +#ifdef LTC_F8_MODE + DO(f8_test_mode()); +#endif + +#ifdef LTC_LRW_MODE + DO(lrw_test()); +#endif + +#ifdef LTC_CBC_MODE + /* test CBC mode */ + /* encode the block */ + DO(cbc_start(cipher_idx, iv, key, 16, 0, &cbc)); + l = sizeof(iv2); + DO(cbc_getiv(iv2, &l, &cbc)); + if (l != 16 || memcmp(iv2, iv, 16)) { + fprintf(stderr, "cbc_getiv failed"); + return 1; + } + DO(cbc_encrypt(pt, ct, 64, &cbc)); + + /* decode the block */ + DO(cbc_setiv(iv2, l, &cbc)); + zeromem(tmp, sizeof(tmp)); + DO(cbc_decrypt(ct, tmp, 64, &cbc)); + if (memcmp(tmp, pt, 64) != 0) { + fprintf(stderr, "CBC failed"); + return 1; + } +#endif + +#ifdef LTC_CFB_MODE + /* test CFB mode */ + /* encode the block */ + DO(cfb_start(cipher_idx, iv, key, 16, 0, &cfb)); + l = sizeof(iv2); + DO(cfb_getiv(iv2, &l, &cfb)); + /* note we don't memcmp iv2/iv since cfb_start processes the IV for the first block */ + if (l != 16) { + fprintf(stderr, "cfb_getiv failed"); + return 1; + } + DO(cfb_encrypt(pt, ct, 64, &cfb)); + + /* decode the block */ + DO(cfb_setiv(iv, l, &cfb)); + zeromem(tmp, sizeof(tmp)); + DO(cfb_decrypt(ct, tmp, 64, &cfb)); + if (memcmp(tmp, pt, 64) != 0) { + fprintf(stderr, "CFB failed"); + return 1; + } +#endif + +#ifdef LTC_OFB_MODE + /* test OFB mode */ + /* encode the block */ + DO(ofb_start(cipher_idx, iv, key, 16, 0, &ofb)); + l = sizeof(iv2); + DO(ofb_getiv(iv2, &l, &ofb)); + if (l != 16 || memcmp(iv2, iv, 16)) { + fprintf(stderr, "ofb_getiv failed"); + return 1; + } + DO(ofb_encrypt(pt, ct, 64, &ofb)); + + /* decode the block */ + DO(ofb_setiv(iv2, l, &ofb)); + zeromem(tmp, sizeof(tmp)); + DO(ofb_decrypt(ct, tmp, 64, &ofb)); + if (memcmp(tmp, pt, 64) != 0) { + fprintf(stderr, "OFB failed"); + return 1; + } +#endif + +#ifdef LTC_CTR_MODE + DO(ctr_test()); +#endif + +#ifdef LTC_XTS_MODE + DO(xts_test()); +#endif + + return 0; +} + +/* $Source: /cvs/libtom/libtomcrypt/testprof/modes_test.c,v $ */ +/* $Revision: 1.15 $ */ +/* $Date: 2007/02/16 16:36:25 $ */ diff --git a/core/lib/libtomcrypt/test/pkcs_1_test.c b/core/lib/libtomcrypt/test/pkcs_1_test.c new file mode 100644 index 00000000000..f56a77edc5c --- /dev/null +++ b/core/lib/libtomcrypt/test/pkcs_1_test.c @@ -0,0 +1,93 @@ +#include + +#ifdef LTC_PKCS_1 + +int pkcs_1_test(void) +{ + unsigned char buf[3][128]; + int res1, res2, res3, prng_idx, hash_idx, err; + unsigned long x, y, l1, l2, l3, i1, i2, lparamlen, saltlen, modlen; + static const unsigned char lparam[] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 }; + + /* get hash/prng */ + hash_idx = find_hash("sha1"); + prng_idx = find_prng("yarrow"); + + if (hash_idx == -1 || prng_idx == -1) { + fprintf(stderr, "pkcs_1 tests require sha1/yarrow"); + return 1; + } + + srand(time(NULL)); + /* do many tests */ + for (x = 0; x < 100; x++) { + zeromem(buf, sizeof(buf)); + + /* make a dummy message (of random length) */ + l3 = (rand() & 31) + 8; + for (y = 0; y < l3; y++) buf[0][y] = rand() & 255; + + /* pick a random lparam len [0..16] */ + lparamlen = abs(rand()) % 17; + + /* pick a random saltlen 0..16 */ + saltlen = abs(rand()) % 17; + + /* LTC_PKCS #1 v2.0 supports modlens not multiple of 8 */ + modlen = 800 + (abs(rand()) % 224); + + /* encode it */ + l1 = sizeof(buf[1]); + DO(pkcs_1_oaep_encode(buf[0], l3, lparam, lparamlen, modlen, &yarrow_prng, prng_idx, hash_idx, buf[1], &l1)); + + /* decode it */ + l2 = sizeof(buf[2]); + DO(pkcs_1_oaep_decode(buf[1], l1, lparam, lparamlen, modlen, hash_idx, buf[2], &l2, &res1)); + + if (res1 != 1 || l2 != l3 || memcmp(buf[2], buf[0], l3) != 0) { + fprintf(stderr, "Outsize == %lu, should have been %lu, res1 = %d, lparamlen = %lu, msg contents follow.\n", l2, l3, res1, lparamlen); + fprintf(stderr, "ORIGINAL:\n"); + for (x = 0; x < l3; x++) { + fprintf(stderr, "%02x ", buf[0][x]); + } + fprintf(stderr, "\nRESULT:\n"); + for (x = 0; x < l2; x++) { + fprintf(stderr, "%02x ", buf[2][x]); + } + fprintf(stderr, "\n\n"); + return 1; + } + + /* test PSS */ + l1 = sizeof(buf[1]); + DO(pkcs_1_pss_encode(buf[0], l3, saltlen, &yarrow_prng, prng_idx, hash_idx, modlen, buf[1], &l1)); + DO(pkcs_1_pss_decode(buf[0], l3, buf[1], l1, saltlen, hash_idx, modlen, &res1)); + + buf[0][i1 = abs(rand()) % l3] ^= 1; + DO(pkcs_1_pss_decode(buf[0], l3, buf[1], l1, saltlen, hash_idx, modlen, &res2)); + + buf[0][i1] ^= 1; + buf[1][i2 = abs(rand()) % (l1 - 1)] ^= 1; + pkcs_1_pss_decode(buf[0], l3, buf[1], l1, saltlen, hash_idx, modlen, &res3); + if (!(res1 == 1 && res2 == 0 && res3 == 0)) { + fprintf(stderr, "PSS failed: %d, %d, %d, %lu, %lu\n", res1, res2, res3, l3, saltlen); + return 1; + } + } + return 0; +} + +#else + +int pkcs_1_test(void) +{ + fprintf(stderr, "NOP"); + return 0; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/testprof/pkcs_1_test.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/test/rsa_test.c b/core/lib/libtomcrypt/test/rsa_test.c new file mode 100644 index 00000000000..7def1e6d026 --- /dev/null +++ b/core/lib/libtomcrypt/test/rsa_test.c @@ -0,0 +1,388 @@ +#include + +#ifdef LTC_MRSA + +#define RSA_MSGSIZE 78 + +/* These are test keys [see file test.key] that I use to test my import/export against */ +static const unsigned char openssl_private_rsa[] = { + 0x30, 0x82, 0x02, 0x5e, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xcf, 0x9a, 0xde, 0x64, 0x8a, + 0xda, 0xc8, 0x33, 0x20, 0xa9, 0xd7, 0x83, 0x31, 0x19, 0x54, 0xb2, 0x9a, 0x85, 0xa7, 0xa1, 0xb7, + 0x75, 0x33, 0xb6, 0xa9, 0xac, 0x84, 0x24, 0xb3, 0xde, 0xdb, 0x7d, 0x85, 0x2d, 0x96, 0x65, 0xe5, + 0x3f, 0x72, 0x95, 0x24, 0x9f, 0x28, 0x68, 0xca, 0x4f, 0xdb, 0x44, 0x1c, 0x3e, 0x60, 0x12, 0x8a, + 0xdd, 0x26, 0xa5, 0xeb, 0xff, 0x0b, 0x5e, 0xd4, 0x88, 0x38, 0x49, 0x2a, 0x6e, 0x5b, 0xbf, 0x12, + 0x37, 0x47, 0xbd, 0x05, 0x6b, 0xbc, 0xdb, 0xf3, 0xee, 0xe4, 0x11, 0x8e, 0x41, 0x68, 0x7c, 0x61, + 0x13, 0xd7, 0x42, 0xc8, 0x80, 0xbe, 0x36, 0x8f, 0xdc, 0x08, 0x8b, 0x4f, 0xac, 0xa4, 0xe2, 0x76, + 0x0c, 0xc9, 0x63, 0x6c, 0x49, 0x58, 0x93, 0xed, 0xcc, 0xaa, 0xdc, 0x25, 0x3b, 0x0a, 0x60, 0x3f, + 0x8b, 0x54, 0x3a, 0xc3, 0x4d, 0x31, 0xe7, 0x94, 0xa4, 0x44, 0xfd, 0x02, 0x03, 0x01, 0x00, 0x01, + 0x02, 0x81, 0x81, 0x00, 0xc8, 0x62, 0xb9, 0xea, 0xde, 0x44, 0x53, 0x1d, 0x56, 0x97, 0xd9, 0x97, + 0x9e, 0x1a, 0xcf, 0x30, 0x1e, 0x0a, 0x88, 0x45, 0x86, 0x29, 0x30, 0xa3, 0x4d, 0x9f, 0x61, 0x65, + 0x73, 0xe0, 0xd6, 0x87, 0x8f, 0xb6, 0xf3, 0x06, 0xa3, 0x82, 0xdc, 0x7c, 0xac, 0xfe, 0x9b, 0x28, + 0x9a, 0xae, 0xfd, 0xfb, 0xfe, 0x2f, 0x0e, 0xd8, 0x97, 0x04, 0xe3, 0xbb, 0x1f, 0xd1, 0xec, 0x0d, + 0xba, 0xa3, 0x49, 0x7f, 0x47, 0xac, 0x8a, 0x44, 0x04, 0x7e, 0x86, 0xb7, 0x39, 0x42, 0x3f, 0xad, + 0x1e, 0xb7, 0x0e, 0xa5, 0x51, 0xf4, 0x40, 0x63, 0x1e, 0xfd, 0xbd, 0xea, 0x9f, 0x41, 0x9f, 0xa8, + 0x90, 0x1d, 0x6f, 0x0a, 0x5a, 0x95, 0x13, 0x11, 0x0d, 0x80, 0xaf, 0x5f, 0x64, 0x98, 0x8a, 0x2c, + 0x78, 0x68, 0x65, 0xb0, 0x2b, 0x8b, 0xa2, 0x53, 0x87, 0xca, 0xf1, 0x64, 0x04, 0xab, 0xf2, 0x7b, + 0xdb, 0x83, 0xc8, 0x81, 0x02, 0x41, 0x00, 0xf7, 0xbe, 0x5e, 0x23, 0xc3, 0x32, 0x3f, 0xbf, 0x8b, + 0x8e, 0x3a, 0xee, 0xfc, 0xfc, 0xcb, 0xe5, 0xf7, 0xf1, 0x0b, 0xbc, 0x42, 0x82, 0xae, 0xd5, 0x7a, + 0x3e, 0xca, 0xf7, 0xd5, 0x69, 0x3f, 0x64, 0x25, 0xa2, 0x1f, 0xb7, 0x75, 0x75, 0x05, 0x92, 0x42, + 0xeb, 0xb8, 0xf1, 0xf3, 0x0a, 0x05, 0xe3, 0x94, 0xd1, 0x55, 0x78, 0x35, 0xa0, 0x36, 0xa0, 0x9b, + 0x7c, 0x92, 0x84, 0x6c, 0xdd, 0xdc, 0x4d, 0x02, 0x41, 0x00, 0xd6, 0x86, 0x0e, 0x85, 0x42, 0x0b, + 0x04, 0x08, 0x84, 0x21, 0x60, 0xf0, 0x0e, 0x0d, 0x88, 0xfd, 0x1e, 0x36, 0x10, 0x65, 0x4f, 0x1e, + 0x53, 0xb4, 0x08, 0x72, 0x80, 0x5c, 0x3f, 0x59, 0x66, 0x17, 0xe6, 0x98, 0xf2, 0xe9, 0x6c, 0x7a, + 0x06, 0x4c, 0xac, 0x76, 0x3d, 0xed, 0x8c, 0xa1, 0xce, 0xad, 0x1b, 0xbd, 0xb4, 0x7d, 0x28, 0xbc, + 0xe3, 0x0e, 0x38, 0x8d, 0x99, 0xd8, 0x05, 0xb5, 0xa3, 0x71, 0x02, 0x40, 0x6d, 0xeb, 0xc3, 0x2d, + 0x2e, 0xf0, 0x5e, 0xa4, 0x88, 0x31, 0x05, 0x29, 0x00, 0x8a, 0xd1, 0x95, 0x29, 0x9b, 0x83, 0xcf, + 0x75, 0xdb, 0x31, 0xe3, 0x7a, 0x27, 0xde, 0x3a, 0x74, 0x30, 0x0c, 0x76, 0x4c, 0xd4, 0x50, 0x2a, + 0x40, 0x2d, 0x39, 0xd9, 0x99, 0x63, 0xa9, 0x5d, 0x80, 0xae, 0x53, 0xca, 0x94, 0x3f, 0x05, 0x23, + 0x1e, 0xf8, 0x05, 0x04, 0xe1, 0xb8, 0x35, 0xf2, 0x17, 0xb3, 0xa0, 0x89, 0x02, 0x41, 0x00, 0xab, + 0x90, 0x88, 0xfa, 0x60, 0x08, 0x29, 0x50, 0x9a, 0x43, 0x8b, 0xa0, 0x50, 0xcc, 0xd8, 0x5a, 0xfe, + 0x97, 0x64, 0x63, 0x71, 0x74, 0x22, 0xa3, 0x20, 0x02, 0x5a, 0xcf, 0xeb, 0xc6, 0x16, 0x95, 0x54, + 0xd1, 0xcb, 0xab, 0x8d, 0x1a, 0xc6, 0x00, 0xfa, 0x08, 0x92, 0x9c, 0x71, 0xd5, 0x52, 0x52, 0x35, + 0x96, 0x71, 0x4b, 0x8b, 0x92, 0x0c, 0xd0, 0xe9, 0xbf, 0xad, 0x63, 0x0b, 0xa5, 0xe9, 0xb1, 0x02, + 0x41, 0x00, 0xdc, 0xcc, 0x27, 0xc8, 0xe4, 0xdc, 0x62, 0x48, 0xd5, 0x9b, 0xaf, 0xf5, 0xab, 0x60, + 0xf6, 0x21, 0xfd, 0x53, 0xe2, 0xb7, 0x5d, 0x09, 0xc9, 0x1a, 0xa1, 0x04, 0xa9, 0xfc, 0x61, 0x2c, + 0x5d, 0x04, 0x58, 0x3a, 0x5a, 0x39, 0xf1, 0x4a, 0x21, 0x56, 0x67, 0xfd, 0xcc, 0x20, 0xa3, 0x8f, + 0x78, 0x18, 0x5a, 0x79, 0x3d, 0x2e, 0x8e, 0x7e, 0x86, 0x0a, 0xe6, 0xa8, 0x33, 0xc1, 0x04, 0x17, + 0x4a, 0x9f, }; + + +/*** openssl public RSA key in DER format */ +static const unsigned char openssl_public_rsa[] = { + 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, + 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xcf, 0x9a, 0xde, + 0x64, 0x8a, 0xda, 0xc8, 0x33, 0x20, 0xa9, 0xd7, 0x83, 0x31, 0x19, 0x54, 0xb2, 0x9a, 0x85, 0xa7, + 0xa1, 0xb7, 0x75, 0x33, 0xb6, 0xa9, 0xac, 0x84, 0x24, 0xb3, 0xde, 0xdb, 0x7d, 0x85, 0x2d, 0x96, + 0x65, 0xe5, 0x3f, 0x72, 0x95, 0x24, 0x9f, 0x28, 0x68, 0xca, 0x4f, 0xdb, 0x44, 0x1c, 0x3e, 0x60, + 0x12, 0x8a, 0xdd, 0x26, 0xa5, 0xeb, 0xff, 0x0b, 0x5e, 0xd4, 0x88, 0x38, 0x49, 0x2a, 0x6e, 0x5b, + 0xbf, 0x12, 0x37, 0x47, 0xbd, 0x05, 0x6b, 0xbc, 0xdb, 0xf3, 0xee, 0xe4, 0x11, 0x8e, 0x41, 0x68, + 0x7c, 0x61, 0x13, 0xd7, 0x42, 0xc8, 0x80, 0xbe, 0x36, 0x8f, 0xdc, 0x08, 0x8b, 0x4f, 0xac, 0xa4, + 0xe2, 0x76, 0x0c, 0xc9, 0x63, 0x6c, 0x49, 0x58, 0x93, 0xed, 0xcc, 0xaa, 0xdc, 0x25, 0x3b, 0x0a, + 0x60, 0x3f, 0x8b, 0x54, 0x3a, 0xc3, 0x4d, 0x31, 0xe7, 0x94, 0xa4, 0x44, 0xfd, 0x02, 0x03, 0x01, + 0x00, 0x01, }; + +/* same key but with extra headers stripped */ +static const unsigned char openssl_public_rsa_stripped[] = { + 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xcf, 0x9a, 0xde, + 0x64, 0x8a, 0xda, 0xc8, 0x33, 0x20, 0xa9, 0xd7, 0x83, 0x31, 0x19, 0x54, 0xb2, 0x9a, 0x85, 0xa7, + 0xa1, 0xb7, 0x75, 0x33, 0xb6, 0xa9, 0xac, 0x84, 0x24, 0xb3, 0xde, 0xdb, 0x7d, 0x85, 0x2d, 0x96, + 0x65, 0xe5, 0x3f, 0x72, 0x95, 0x24, 0x9f, 0x28, 0x68, 0xca, 0x4f, 0xdb, 0x44, 0x1c, 0x3e, 0x60, + 0x12, 0x8a, 0xdd, 0x26, 0xa5, 0xeb, 0xff, 0x0b, 0x5e, 0xd4, 0x88, 0x38, 0x49, 0x2a, 0x6e, 0x5b, + 0xbf, 0x12, 0x37, 0x47, 0xbd, 0x05, 0x6b, 0xbc, 0xdb, 0xf3, 0xee, 0xe4, 0x11, 0x8e, 0x41, 0x68, + 0x7c, 0x61, 0x13, 0xd7, 0x42, 0xc8, 0x80, 0xbe, 0x36, 0x8f, 0xdc, 0x08, 0x8b, 0x4f, 0xac, 0xa4, + 0xe2, 0x76, 0x0c, 0xc9, 0x63, 0x6c, 0x49, 0x58, 0x93, 0xed, 0xcc, 0xaa, 0xdc, 0x25, 0x3b, 0x0a, + 0x60, 0x3f, 0x8b, 0x54, 0x3a, 0xc3, 0x4d, 0x31, 0xe7, 0x94, 0xa4, 0x44, 0xfd, 0x02, 0x03, 0x01, + 0x00, 0x01, }; + +static int rsa_compat_test(void) +{ + rsa_key key; + unsigned char buf[1024]; + unsigned long len; + + /* try reading the key */ + DO(rsa_import(openssl_private_rsa, sizeof(openssl_private_rsa), &key)); + + /* now try to export private/public and compare */ + len = sizeof(buf); + DO(rsa_export(buf, &len, PK_PRIVATE, &key)); + if (len != sizeof(openssl_private_rsa) || memcmp(buf, openssl_private_rsa, len)) { + fprintf(stderr, "RSA private export failed to match OpenSSL output, %lu, %lu\n", len, (unsigned long)sizeof(openssl_private_rsa)); + return 1; + } + + len = sizeof(buf); + DO(rsa_export(buf, &len, PK_PUBLIC, &key)); + if (len != sizeof(openssl_public_rsa_stripped) || memcmp(buf, openssl_public_rsa_stripped, len)) { + fprintf(stderr, "RSA(private) public export failed to match OpenSSL output\n"); + return 1; + } + rsa_free(&key); + + /* try reading the public key */ + DO(rsa_import(openssl_public_rsa_stripped, sizeof(openssl_public_rsa_stripped), &key)); + len = sizeof(buf); + DO(rsa_export(buf, &len, PK_PUBLIC, &key)); + if (len != sizeof(openssl_public_rsa_stripped) || memcmp(buf, openssl_public_rsa_stripped, len)) { + fprintf(stderr, "RSA(public) stripped public import failed to match OpenSSL output\n"); + return 1; + } + rsa_free(&key); + + /* try reading the public key */ + DO(rsa_import(openssl_public_rsa, sizeof(openssl_public_rsa), &key)); + len = sizeof(buf); + DO(rsa_export(buf, &len, PK_PUBLIC, &key)); + if (len != sizeof(openssl_public_rsa_stripped) || memcmp(buf, openssl_public_rsa_stripped, len)) { + fprintf(stderr, "RSA(public) SSL public import failed to match OpenSSL output\n"); + return 1; + } + rsa_free(&key); + + return 0; +} + +int rsa_test(void) +{ + unsigned char in[1024], out[1024], tmp[1024]; + rsa_key key, privKey, pubKey; + int hash_idx, prng_idx, stat, stat2; + unsigned long rsa_msgsize, len, len2, cnt; + static unsigned char lparam[] = { 0x01, 0x02, 0x03, 0x04 }; + + if (rsa_compat_test() != 0) { + return 1; + } + + hash_idx = find_hash("sha1"); + prng_idx = find_prng("yarrow"); + if (hash_idx == -1 || prng_idx == -1) { + fprintf(stderr, "rsa_test requires LTC_SHA1 and yarrow"); + return 1; + } + + /* make 10 random key */ + for (cnt = 0; cnt < 10; cnt++) { + DO(rsa_make_key(&yarrow_prng, prng_idx, 1024/8, 65537, &key)); + if (mp_count_bits(key.N) != 1024) { + fprintf(stderr, "rsa_1024 key modulus has %d bits\n", mp_count_bits(key.N)); + + len = mp_unsigned_bin_size(key.N); + mp_to_unsigned_bin(key.N, tmp); + fprintf(stderr, "N == \n"); + for (cnt = 0; cnt < len; ) { + fprintf(stderr, "%02x ", tmp[cnt]); + if (!(++cnt & 15)) fprintf(stderr, "\n"); + } + + len = mp_unsigned_bin_size(key.p); + mp_to_unsigned_bin(key.p, tmp); + fprintf(stderr, "p == \n"); + for (cnt = 0; cnt < len; ) { + fprintf(stderr, "%02x ", tmp[cnt]); + if (!(++cnt & 15)) fprintf(stderr, "\n"); + } + + len = mp_unsigned_bin_size(key.q); + mp_to_unsigned_bin(key.q, tmp); + fprintf(stderr, "\nq == \n"); + for (cnt = 0; cnt < len; ) { + fprintf(stderr, "%02x ", tmp[cnt]); + if (!(++cnt & 15)) fprintf(stderr, "\n"); + } + fprintf(stderr, "\n"); + + + return 1; + } + if (cnt != 9) { + rsa_free(&key); + } + } + + /* encrypt the key (without lparam) */ + for (cnt = 0; cnt < 4; cnt++) { + for (rsa_msgsize = 1; rsa_msgsize <= 86; rsa_msgsize++) { + /* make a random key/msg */ + yarrow_read(in, rsa_msgsize, &yarrow_prng); + + len = sizeof(out); + len2 = rsa_msgsize; + + DO(rsa_encrypt_key(in, rsa_msgsize, out, &len, NULL, 0, &yarrow_prng, prng_idx, hash_idx, &key)); + /* change a byte */ + out[8] ^= 1; + DO(rsa_decrypt_key(out, len, tmp, &len2, NULL, 0, hash_idx, &stat2, &key)); + /* change a byte back */ + out[8] ^= 1; + stat2 = 0; + if (len2 != rsa_msgsize) { + fprintf(stderr, "\nrsa_decrypt_key mismatch len %lu (first decrypt)", len2); + return 1; + } + + len2 = rsa_msgsize; + DO(rsa_decrypt_key(out, len, tmp, &len2, NULL, 0, hash_idx, &stat, &key)); + if (!(stat == 1 && stat2 == 0)) { + fprintf(stderr, "rsa_decrypt_key failed"); + return 1; + } + if (len2 != rsa_msgsize || memcmp(tmp, in, rsa_msgsize)) { + unsigned long x; + fprintf(stderr, "\nrsa_decrypt_key mismatch, len %lu (second decrypt)\n", len2); + fprintf(stderr, "Original contents: \n"); + for (x = 0; x < rsa_msgsize; ) { + fprintf(stderr, "%02x ", in[x]); + if (!(++x % 16)) { + fprintf(stderr, "\n"); + } + } + fprintf(stderr, "\n"); + fprintf(stderr, "Output contents: \n"); + for (x = 0; x < rsa_msgsize; ) { + fprintf(stderr, "%02x ", out[x]); + if (!(++x % 16)) { + fprintf(stderr, "\n"); + } + } + fprintf(stderr, "\n"); + return 1; + } + } + } + + /* encrypt the key (with lparam) */ + for (rsa_msgsize = 1; rsa_msgsize <= 86; rsa_msgsize++) { + len = sizeof(out); + len2 = rsa_msgsize; + DO(rsa_encrypt_key(in, rsa_msgsize, out, &len, lparam, sizeof(lparam), &yarrow_prng, prng_idx, hash_idx, &key)); + /* change a byte */ + out[8] ^= 1; + DO(rsa_decrypt_key(out, len, tmp, &len2, lparam, sizeof(lparam), hash_idx, &stat2, &key)); + if (len2 != rsa_msgsize) { + fprintf(stderr, "\nrsa_decrypt_key mismatch len %lu (first decrypt)", len2); + return 1; + } + /* change a byte back */ + out[8] ^= 1; + + len2 = rsa_msgsize; + DO(rsa_decrypt_key(out, len, tmp, &len2, lparam, sizeof(lparam), hash_idx, &stat, &key)); + if (!(stat == 1 && stat2 == 0)) { + fprintf(stderr, "rsa_decrypt_key failed"); + return 1; + } + if (len2 != rsa_msgsize || memcmp(tmp, in, rsa_msgsize)) { + fprintf(stderr, "rsa_decrypt_key mismatch len %lu", len2); + return 1; + } + } + + /* encrypt the key LTC_PKCS #1 v1.5 (payload from 1 to 117 bytes) */ + for (rsa_msgsize = 1; rsa_msgsize <= 117; rsa_msgsize++) { + len = sizeof(out); + len2 = rsa_msgsize; + DO(rsa_encrypt_key_ex(in, rsa_msgsize, out, &len, NULL, 0, &yarrow_prng, prng_idx, 0, LTC_LTC_PKCS_1_V1_5, &key)); + + len2 = rsa_msgsize; + DO(rsa_decrypt_key_ex(out, len, tmp, &len2, NULL, 0, 0, LTC_LTC_PKCS_1_V1_5, &stat, &key)); + if (!(stat == 1 && stat2 == 0)) { + fprintf(stderr, "rsa_decrypt_key_ex failed, %d, %d", stat, stat2); + return 1; + } + if (len2 != rsa_msgsize || memcmp(tmp, in, rsa_msgsize)) { + fprintf(stderr, "rsa_decrypt_key_ex mismatch len %lu", len2); + return 1; + } + } + + /* sign a message (unsalted, lower cholestorol and Atkins approved) now */ + len = sizeof(out); + DO(rsa_sign_hash(in, 20, out, &len, &yarrow_prng, prng_idx, hash_idx, 0, &key)); + + /* export key and import as both private and public */ + len2 = sizeof(tmp); + DO(rsa_export(tmp, &len2, PK_PRIVATE, &key)); + DO(rsa_import(tmp, len2, &privKey)); + len2 = sizeof(tmp); + DO(rsa_export(tmp, &len2, PK_PUBLIC, &key)); + DO(rsa_import(tmp, len2, &pubKey)); + + /* verify with original */ + DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat, &key)); + /* change a byte */ + in[0] ^= 1; + DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat2, &key)); + + if (!(stat == 1 && stat2 == 0)) { + fprintf(stderr, "rsa_verify_hash (unsalted, origKey) failed, %d, %d", stat, stat2); + rsa_free(&key); + rsa_free(&pubKey); + rsa_free(&privKey); + return 1; + } + + /* verify with privKey */ + /* change a byte */ + in[0] ^= 1; + DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat, &privKey)); + /* change a byte */ + in[0] ^= 1; + DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat2, &privKey)); + + if (!(stat == 1 && stat2 == 0)) { + fprintf(stderr, "rsa_verify_hash (unsalted, privKey) failed, %d, %d", stat, stat2); + rsa_free(&key); + rsa_free(&pubKey); + rsa_free(&privKey); + return 1; + } + + /* verify with pubKey */ + /* change a byte */ + in[0] ^= 1; + DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat, &pubKey)); + /* change a byte */ + in[0] ^= 1; + DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat2, &pubKey)); + + if (!(stat == 1 && stat2 == 0)) { + fprintf(stderr, "rsa_verify_hash (unsalted, pubkey) failed, %d, %d", stat, stat2); + rsa_free(&key); + rsa_free(&pubKey); + rsa_free(&privKey); + return 1; + } + + /* sign a message (salted) now (use privKey to make, pubKey to verify) */ + len = sizeof(out); + DO(rsa_sign_hash(in, 20, out, &len, &yarrow_prng, prng_idx, hash_idx, 8, &privKey)); + DO(rsa_verify_hash(out, len, in, 20, hash_idx, 8, &stat, &pubKey)); + /* change a byte */ + in[0] ^= 1; + DO(rsa_verify_hash(out, len, in, 20, hash_idx, 8, &stat2, &pubKey)); + + if (!(stat == 1 && stat2 == 0)) { + fprintf(stderr, "rsa_verify_hash (salted) failed, %d, %d", stat, stat2); + rsa_free(&key); + rsa_free(&pubKey); + rsa_free(&privKey); + return 1; + } + + /* sign a message with LTC_PKCS #1 v1.5 */ + len = sizeof(out); + DO(rsa_sign_hash_ex(in, 20, out, &len, LTC_LTC_PKCS_1_V1_5, &yarrow_prng, prng_idx, hash_idx, 8, &privKey)); + DO(rsa_verify_hash_ex(out, len, in, 20, LTC_LTC_PKCS_1_V1_5, hash_idx, 8, &stat, &pubKey)); + /* change a byte */ + in[0] ^= 1; + DO(rsa_verify_hash_ex(out, len, in, 20, LTC_LTC_PKCS_1_V1_5, hash_idx, 8, &stat2, &pubKey)); + + if (!(stat == 1 && stat2 == 0)) { + fprintf(stderr, "rsa_verify_hash_ex failed, %d, %d", stat, stat2); + rsa_free(&key); + rsa_free(&pubKey); + rsa_free(&privKey); + return 1; + } + + /* free the key and return */ + rsa_free(&key); + rsa_free(&pubKey); + rsa_free(&privKey); + return 0; +} + +#else + +int rsa_test(void) +{ + fprintf(stderr, "NOP"); + return 0; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/testprof/rsa_test.c,v $ */ +/* $Revision: 1.20 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/core/lib/libtomcrypt/test/store_test.c b/core/lib/libtomcrypt/test/store_test.c new file mode 100644 index 00000000000..5a38d65082b --- /dev/null +++ b/core/lib/libtomcrypt/test/store_test.c @@ -0,0 +1,78 @@ +#include + +/* Test store/load macros with offsets */ +int store_test(void) +{ + unsigned char buf[256]; + int y; + ulong32 L, L1; + ulong64 LL, LL1; +#ifdef LTC_FAST + int x, z; +#endif + + for (y = 0; y < 4; y++) { + L = 0x12345678UL; + L1 = 0; + STORE32L(L, buf + y); + LOAD32L(L1, buf + y); + if (L1 != L) { + fprintf(stderr, "\n32L failed at offset %d\n", y); + return 1; + } + STORE32H(L, buf + y); + LOAD32H(L1, buf + y); + if (L1 != L) { + fprintf(stderr, "\n32H failed at offset %d\n", y); + return 1; + } + } + + for (y = 0; y < 8; y++) { + LL = CONST64 (0x01020304050607); + LL1 = 0; + STORE64L(LL, buf + y); + LOAD64L(LL1, buf + y); + if (LL1 != LL) { + fprintf(stderr, "\n64L failed at offset %d\n", y); + return 1; + } + STORE64H(LL, buf + y); + LOAD64H(LL1, buf + y); + if (LL1 != LL) { + fprintf(stderr, "\n64H failed at offset %d\n", y); + return 1; + } + } + +/* test LTC_FAST */ +#ifdef LTC_FAST + y = 16; + + for (z = 0; z < y; z++) { + /* fill y bytes with random */ + yarrow_read(buf+z, y, &yarrow_prng); + yarrow_read(buf+z+y, y, &yarrow_prng); + + /* now XOR it byte for byte */ + for (x = 0; x < y; x++) { + buf[2*y+z+x] = buf[z+x] ^ buf[z+y+x]; + } + + /* now XOR it word for word */ + for (x = 0; x < y; x += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE*)(&buf[3*y+z+x])) = *((LTC_FAST_TYPE*)(&buf[z+x])) ^ *((LTC_FAST_TYPE*)(&buf[z+y+x])); + } + + if (memcmp(&buf[2*y+z], &buf[3*y+z], y)) { + fprintf(stderr, "\nLTC_FAST failed at offset %d\n", z); + return 1; + } + } +#endif + return 0; +} + +/* $Source: /cvs/libtom/libtomcrypt/testprof/store_test.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2005/05/05 14:35:59 $ */ diff --git a/core/lib/libtomcrypt/test/test.c b/core/lib/libtomcrypt/test/test.c new file mode 100644 index 00000000000..51c76027775 --- /dev/null +++ b/core/lib/libtomcrypt/test/test.c @@ -0,0 +1,77 @@ +#include +#include "tomcrypt_mpa.h" +#include +#include + + +#define LTC_VARIABLE_NUMBER (50) +#define LTC_MAX_BITS_PER_VARIABLE (2048) + +static uint32_t mempool_u32[ mpa_scratch_mem_size_in_U32(LTC_VARIABLE_NUMBER, LTC_MAX_BITS_PER_VARIABLE) ]; +static mpa_scratch_mem pool; + +void __init(const uint32_t number_of_variable, const uint32_t bits_per_variable) { + if ((number_of_variable * bits_per_variable) > (LTC_VARIABLE_NUMBER * LTC_MAX_BITS_PER_VARIABLE)) { + fprintf(stderr, "Requested Memory is greater than available !!\n"); + exit(EXIT_FAILURE); + } + pool = (mpa_scratch_mem_base *) &mempool_u32; + init_mpa_tomcrypt(pool); + mpa_init_scratch_mem(pool, number_of_variable, bits_per_variable); + // __mpa_init_random(0xdeadbeef); +} + +static int __check_memory(void) { + int idx; + mpa_num_base* tvar; + + idx = 0; + tvar =(void*)pool->m; + while (tvar->alloc == 0 && idx < pool->nrof_vars) { + tvar = (void*)&pool->m[idx * mpa_StaticTempVarSizeInU32(pool->bit_size)]; + idx++; + } + return (idx == pool->nrof_vars) ? CRYPT_OK : CRYPT_MEM; +} + +#define CHECK_MEM do { \ + err = __check_memory(); \ + if (x) exit(EXIT_FAILURE); \ +}while(0) + +int main(void) +{ + int x, err = CRYPT_OK; + + reg_algs(); + __init(40, 2048); + + printf("\nunit_test....."), fflush(stdout); x = unit_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); + CHECK_MEM; + printf("\nstore_test...."); fflush(stdout); x = store_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); + CHECK_MEM; + printf("\ncipher_test..."); fflush(stdout); x = cipher_hash_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); + CHECK_MEM; + printf("\nmodes_test...."); fflush(stdout); x = modes_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); + CHECK_MEM; + printf("\nmac_test......"); fflush(stdout); x = mac_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); + CHECK_MEM; + printf("\npkcs_1_test..."); fflush(stdout); x = pkcs_1_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); + CHECK_MEM; + printf("\nder_test......"); fflush(stdout); x = der_tests(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); + CHECK_MEM; + printf("\nrsa_test......"); fflush(stdout); x = rsa_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); + CHECK_MEM; + __init(90, 2*521); + printf("\necc_test......"); fflush(stdout); x = ecc_tests(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); + CHECK_MEM; + __init(40, 2048); + printf("\ndsa_test......"); fflush(stdout); x = dsa_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); + CHECK_MEM; + printf("\n"); + return err; +} + +/* $Source: /cvs/libtom/libtomcrypt/demos/test.c,v $ */ +/* $Revision: 1.28 $ */ +/* $Date: 2006/05/25 10:50:08 $ */ diff --git a/core/lib/libtomcrypt/test/test_driver.c b/core/lib/libtomcrypt/test/test_driver.c new file mode 100644 index 00000000000..25740a03983 --- /dev/null +++ b/core/lib/libtomcrypt/test/test_driver.c @@ -0,0 +1,15 @@ +#include + +void run_cmd(int res, int line, char *file, char *cmd) +{ + if (res != CRYPT_OK) { + fprintf(stderr, "%s (%d)\n%s:%d:%s\n", error_to_string(res), res, file, line, cmd); + if (res != CRYPT_NOP) { + exit(EXIT_FAILURE); + } + } +} + +/* $Source: /cvs/libtom/libtomcrypt/testprof/test_driver.c,v $ */ +/* $Revision: 1.2 $ */ +/* $Date: 2006/11/13 23:14:33 $ */ diff --git a/core/lib/libtomcrypt/test/tomcrypt_test.h b/core/lib/libtomcrypt/test/tomcrypt_test.h new file mode 100644 index 00000000000..606c4ae0441 --- /dev/null +++ b/core/lib/libtomcrypt/test/tomcrypt_test.h @@ -0,0 +1,84 @@ + +#ifndef __TEST_H_ +#define __TEST_H_ + +#include + +/* enable stack testing */ +/* #define STACK_TEST */ + +/* stack testing, define this if stack usage goes downwards [e.g. x86] */ +#define STACK_DOWN + +typedef struct { + char *name, *prov, *req; + int (*entry)(void); +} test_entry; + +extern prng_state yarrow_prng; + +void run_cmd(int res, int line, char *file, char *cmd); + +#ifdef LTC_VERBOSE +#define DO(x) do { fprintf(stderr, "%s:\n", #x); run_cmd((x), __LINE__, __FILE__, #x); } while (0); +#else +#define DO(x) do { run_cmd((x), __LINE__, __FILE__, #x); } while (0); +#endif + +/* TESTS */ +int unit_test(void); +int cipher_hash_test(void); +int modes_test(void); +int mac_test(void); +int pkcs_1_test(void); +int store_test(void); +int rsa_test(void); +int katja_test(void); +int ecc_tests(void); +int dsa_test(void); +int der_tests(void); + +/* timing */ +#define KTIMES 25 +#define TIMES 100000 + +extern struct list { + int id; + unsigned long spd1, spd2, avg; +} results[]; + +extern int no_results; + +int sorter(const void *a, const void *b); +void tally_results(int type); +ulong64 rdtsc (void); + +void t_start(void); +ulong64 t_read(void); +void init_timer(void); + +/* register default algs */ +void reg_algs(void); +int time_keysched(void); +int time_cipher(void); +int time_cipher2(void); +int time_cipher3(void); +int time_hash(void); +void time_mult(void); +void time_sqr(void); +void time_prng(void); +void time_rsa(void); +void time_dsa(void); +void time_katja(void); +void time_ecc(void); +void time_macs_(unsigned long MAC_SIZE); +void time_macs(void); +void time_encmacs(void); + + + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/testprof/tomcrypt_test.h,v $ */ +/* $Revision: 1.14 $ */ +/* $Date: 2006/10/18 03:36:34 $ */ diff --git a/core/lib/libtomcrypt/test/unit_test.c b/core/lib/libtomcrypt/test/unit_test.c new file mode 100644 index 00000000000..fbb7afe0fed --- /dev/null +++ b/core/lib/libtomcrypt/test/unit_test.c @@ -0,0 +1,1653 @@ +//----------------------------------------------------------------------------- +// +// Copyright 2013, STMicroelectronics - All Rights Reserved +// +// ST makes no warranty express or implied including but not limited to, +// any warranty of (i) merchantability or fitness for a particular purpose +// and/or (ii) requirements, for a particular purpose in relation to the +// LICENSED MATERIALS, which is provided "AS IS", WITH ALL FAULTS. +// +// ST does not represent or warrant that the LICENSED MATERIALS provided +// hereunder is free of infringement of any third party patents, copyrights, +// trade secrets or other intellectual property rights. +// +// ALL WARRANTIES, CONDITIONS OR OTHER TERMS IMPLIED BY LAW ARE EXCLUDED +// TO THE FULLEST EXTENT PERMITTED BY LAW. +// +//----------------------------------------------------------------------------- + + +/* + * unit_test.c + * + * Created on: 22 janv. 2014 + * Author: michael adjedj + */ + +#include "tomcrypt_test.h" +#include "tomcrypt_mpa.h" + + +static int ltc_test_neg(void) { + void *a, *b; + unsigned char buf[64]; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, &b, NULL)) != CRYPT_OK) { + return err; + } + for (i = 0; i < 10; ++i) { + if (yarrow_read(buf, sizeof(buf), &yarrow_prng) != sizeof(buf)) { + err = CRYPT_ERROR_READPRNG; + break; + } + mp_read_unsigned_bin(a, buf, sizeof(buf)); + mp_neg(a, b); + mp_add(a, b, a); + if (mp_iszero(a) == LTC_MP_NO) { + err = CRYPT_ERROR; + break; + } + } + + mp_clear_multi(a, b, NULL); + return err; +} + + +static int ltc_test_add_neg(void) { + void *a, *b, *c; + unsigned char buf[64]; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, &b, &c, NULL)) != CRYPT_OK) { + return err; + } + for (i = 0; i < 10; ++i) { + if (yarrow_read(buf, sizeof(buf), &yarrow_prng) != sizeof(buf)) { + err = CRYPT_ERROR_READPRNG; + break; + } + mp_read_unsigned_bin(a, buf, sizeof(buf)); + mp_neg(a, b); + mp_add(a, b, c); // at this po�int c = 0 + mp_add(a, c, b); // b = a+c + + if (mp_cmp(a, b) != LTC_MP_EQ) { + err = CRYPT_ERROR; + break; + } + + mp_add(c, c, a); // we will check that 0+0=0 + if (mp_iszero(a) == LTC_MP_NO) { + err = CRYPT_ERROR; + break; + } + + } + + mp_clear_multi(a, b, c, NULL); + return err; +} + +static int ltc_test_copy(void) { + void *a, *b; + unsigned char buf[64]; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, &b, NULL)) != CRYPT_OK) { + return err; + } + for (i = 0; i < 10; ++i) { + if (yarrow_read(buf, sizeof(buf), &yarrow_prng) != sizeof(buf)) { + err = CRYPT_ERROR_READPRNG; + break; + } + mp_read_unsigned_bin(a, buf, sizeof(buf)); + mp_copy(a, b); + if (mp_cmp(a, b) != LTC_MP_EQ) { + err = CRYPT_ERROR; + break; + } + } + + mp_clear_multi(a, b, NULL); + return err; +} + +static int ltc_test_set_int(void) { + void *a; + unsigned int b; + unsigned char buf[4]; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, NULL)) != CRYPT_OK) { + return err; + } + mp_set_int(a, 0); + if (mp_iszero(a) == LTC_MP_NO) {return CRYPT_ERROR;} + + for (i = 0; i < 10; ++i) { + if (yarrow_read(buf, sizeof(buf), &yarrow_prng) != sizeof(buf)) { + err = CRYPT_ERROR_READPRNG; + break; + } + b = (buf[0] & 0xFF) << 24 | + (buf[1] & 0xFF) << 16 | + (buf[2] & 0xFF) << 8 | + (buf[3] & 0xFF); + mp_set_int(a, b); + if (mp_cmp_d(a, b) != LTC_MP_EQ) { + err = CRYPT_ERROR; + break; + } + } + mp_clear_multi(a, NULL); + return err; +} + +static int ltc_test_count_bits(void) { + void *a; + unsigned int b; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, NULL)) != CRYPT_OK) { + return err; + } + mp_set_int(a, 0); + if (mp_count_bits(a) != 0) {err = CRYPT_ERROR; goto end;} + for (i = 0; i < 20; ++i) { + mp_set_int(a, (1 << i)); + if (mp_count_bits(a) != (i + 1)) {err = CRYPT_ERROR; goto end;} + } + static struct { + const char *str; + unsigned int bits; + } tmp_array[21] = { + {"A262452026EC56EB", 64}, + {"4E3E24506BAD88F1", 63}, + {"52B4CB6FDCF2FC01", 63}, + {"A4BAB4B2CFE0F15C", 64}, + {"A4BAB4B2CFE0F15C", 64}, + {"42E14B83E4CEF5F1", 63}, + {"CE468E9348D34090", 64}, + {"AB57F185A4AC63DB", 64}, + {"DDE1ED2CE0216A5D", 64}, + {"F5E7447C102026AE", 64}, + {"5940E91438D725E0", 63}, + {"D2B5E6B8428E63384580A1909FD3", 112}, + {"1F629132D169638C99BED939", 93}, + {"23256A481939E8FE087FB9432875", 110}, + {"D58B81", 24}, + {"04BBBD2E73E4B1CE76EDA88F", 91}, + {"15", 5}, + {"010FA14334E938B9CF9D9F87D9FDCD", 113}, + {"0127407F95", 33}, + {"0FC1669752C6610E4E7594BFAB", 100}, + {"01797B0E6A26805B309986C4", 89} + }; + + for (i = 0; i < 21; ++i) { + mp_read_radix(a, tmp_array[i].str, 16); + if (mp_count_bits(a) != tmp_array[i].bits) { + err = CRYPT_ERROR; + break; + } + } + + end: + mp_clear_multi(a, NULL); + return err; +} + + + +static int ltc_test_cnt_lsb(void) { + void *a; + unsigned int b; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, NULL)) != CRYPT_OK) { + return err; + } + mp_set_int(a, 0); + if (mp_cnt_lsb(a) != 0) {err = CRYPT_ERROR; goto end;} + + for (i = 0; i < 20; ++i) { + mp_set_int(a, (1 << i)); + if (mp_cnt_lsb(a) != i) {err = CRYPT_ERROR; goto end;} + } + static struct { + const char *str; + unsigned int bits; + } tmp_array[20] = { + {"034F30E9E786C81FC00000000000", 46}, + {"480F81294DBDA098000000000000", 51}, + {"D742AD5CF8456330", 4}, + {"0BD7D81ED89023F5000000000000", 48}, + {"087D5C6B9125644C00000000000000", 58}, + {"0625E2DC4646743D", 0}, + {"3AAC049EBDEDC850000000000000", 52}, + {"2E895911AA09E95400000000000000", 58}, + {"581820BDFFA9FE900000", 20}, + {"070A1296D049EA9D0000000000", 40}, + {"09D8EB7587A7AA530000000000", 40}, + {"03BE8E02495D8A3100", 8}, + {"7FC76B523F8DDE100000", 20}, + {"11ABA2E8DBA40E440000", 18}, + {"05B04B82FC80F94E8000", 15}, + {"9201C4DFB4926FC0000000000000", 54}, + {"8B90BD27558509D0000000000000", 52}, + {"039FFA35199631F10000", 16}, + {"A8894818802278A000000000", 37}, + {"0BE48C2012FC7EBD000000", 24} + }; + + for (i = 0; i < 20; ++i) { + mp_read_radix(a, tmp_array[i].str, 16); + if (mp_cnt_lsb(a) != tmp_array[i].bits) { + err = CRYPT_ERROR; + break; + } + } + + end: + mp_clear_multi(a, NULL); + return err; +} + +static int ltc_test_2expt(void) { + void *a, *b; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, &b, NULL)) != CRYPT_OK) { + return err; + } + + for (i = 0; i < 20; ++i) { + mp_2expt(a, i); + if (mp_cnt_lsb(a) != i || mp_count_bits(a) != (i+1)) {err = CRYPT_ERROR; goto end;} + } + static struct { + const char *str; + unsigned int bits; + } tmp_array[20] = { + {"80000000", 31}, + {"800000000000000", 59}, + {"2000000", 25}, + {"10000000000000000000", 76}, + {"4000000000000000000000000000", 110}, + {"4", 2}, + {"80000000000000000000000000000", 115}, + {"80000000000", 43}, + {"10000000000000000000000000", 100}, + {"10000000000000000000000000", 100}, + {"2000000000000000000", 73}, + {"1000000000000000000", 72}, + {"80000000000000000", 67}, + {"2000000000000", 49}, + {"2000000000000000000000000000", 109}, + {"1000", 12}, + {"200000000000", 45}, + {"40", 6}, + {"400", 10}, + {"200000000000000", 57}, + }; + + for (i = 0; i < 20; ++i) { + mp_read_radix(a, tmp_array[i].str, 16); + mp_2expt(b, tmp_array[i].bits); + if (mp_cmp(a, b) != LTC_MP_EQ) { + err = CRYPT_ERROR; + break; + } + } + + end: + mp_clear_multi(a, b, NULL); + return err; +} + +static int ltc_test_toradix(void) { + void *a, *b; + unsigned char buf[64]; + char sA[(sizeof(buf) * 2) + 1]; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, &b, NULL)) != CRYPT_OK) { + return err; + } + for (i = 0; i < 10; ++i) { + if (yarrow_read(buf, sizeof(buf), &yarrow_prng) != sizeof(buf)) { + err = CRYPT_ERROR_READPRNG; + break; + } + mp_read_unsigned_bin(a, buf, sizeof(buf)); + + mp_toradix(a, sA, 16); + mp_read_radix(b, sA, 16); + if (mp_cmp(a, b) != LTC_MP_EQ) { + err = CRYPT_ERROR; + break; + } + } + + mp_clear_multi(a, b, NULL); + return err; +} + +static int ltc_test_add(void) { + void *a, *b, *c; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, &b, &c, NULL)) != CRYPT_OK) { + return err; + } + + static struct { + const char *str1; + const char *str2; + const char *res; + } tmp_array[20] = { + {"86BE92979876D22AB7A642B35A91AE", "359C5C03019EBA57C292B84C45DA18", "BC5AEE9A9A158C827A38FAFFA06BC6"}, + {"8331801C30A80617551C3782742276", "BA745B46343CF47A747969B4D8AC31", "013DA5DB6264E4FA91C995A1374CCEA7"}, + {"BD0D498E832D1A8C986E8E7AC63117", "85C4609F6D2F229434A02A75ECED77", "0142D1AA2DF05C3D20CD0EB8F0B31E8E"}, + {"B338A219F9E90E9EE63FD7400F4815", "7E2FB75BE3D01C39BCC55B5F1F0D2A", "0131685975DDB92AD8A305329F2E553F"}, + {"F550C826E1D6F5EBC8AA160329ECA7", "AE206BDAB8EE0E0769C5B8CF39D15B", "01A37134019AC503F3326FCED263BE02"}, + {"B264BF569B3261D2EBDC1BA4C88205", "F343BCA8A2306ACCE71E26F3A90BBF", "01A5A87BFF3D62CC9FD2FA4298718DC4"}, + {"C86A83D3C53A5CD01236B9773E90F2", "6BF0C1AAFD00A1C0A5659A2C01BBCD", "01345B457EC23AFE90B79C53A3404CBF"}, + {"F8EA984C204ECE149D71536DA963AA", "80231AF45AF8A8CECC69E92AAE89AF", "01790DB3407B4776E369DB3C9857ED59"}, + {"9DF1B95EC8B8175999CFDCCBB8FC6D", "C3BDC77B52E5B756DE7EF5683B2F0A", "0161AF80DA1B9DCEB0784ED233F42B77"}, + {"5CDF96503C3E796A9FF70C3EA3FB65", "FB5202ED9498303D53C4DA7AA60888", "015831993DD0D6A9A7F3BBE6B94A03ED"}, + {"EEE635FF949BB3CC0D6377334891F8", "EEB09D9EE371AE0ED15B60A6BE98F9", "01DD96D39E780D61DADEBED7DA072AF1"}, + {"492036982EB5F79BD6C41DAA5A335F", "E941937D89F1595D57883E1875D791", "013261CA15B8A750F92E4C5BC2D00AF0"}, + {"E66C4554240CAA4878FDACB2DADD6C", "808D5851BA1EE3DAD8AF76F4A6E0C6", "0166F99DA5DE2B8E2351AD23A781BE32"}, + {"5C3AC188988481BA177F860BEEB92E", "FC3BDCC2AD0A7B1C96AFAF3042598F", "0158769E4B458EFCD6AE2F353C3112BD"}, + {"DF6108AFDA82830CF624E5F05595DC", "DD10C9953148F3ACDDF019A9D96D1E", "01BC71D2450BCB76B9D414FF9A2F02FA"}, + {"282838D8D65993D408C1593C4CCDE2", "D046BF88D0723BD4D2A2AC02531E25", "F86EF861A6CBCFA8DB64053E9FEC07"}, + {"BAB64A57A23E1071F2BB65FF838FE7", "B2A8FD42121C42BB5B2010B74BEC", "BB68F354E4502CB4AE1686103ADBD3"}, + {"103AD57C5E3639526AB921C655332E", "FACCAA04F3360BCB79244BFD5AD154", "010B077F81516C451DE3DD6DC3B00482"}, + {"FB743CD3D6724F2025B2C38E6D46", "25051382AAE6E199AD4F3CD3FE497B", "260087BF7EBD53E8CD74EF978CB6C1"}, + {"82FDD9396B8FDA2DFDD351F6B939B1", "C81E91B43B0A590CA184DBE6EEFDD7", "014B1C6AEDA69A333A9F582DDDA83788"} + }; + + for (i = 0; i < 20; ++i) { + mp_read_radix(a, tmp_array[i].str1, 16); + mp_read_radix(b, tmp_array[i].str2, 16); + mp_read_radix(c, tmp_array[i].res, 16); + mp_add(a, b, a); + if (mp_cmp(a, c) != LTC_MP_EQ) { + err = CRYPT_ERROR; + break; + } + } + + mp_clear_multi(a, b, c, NULL); + return err; +} + + +static int ltc_test_add_d(void) { + void *a, *b; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, &b, NULL)) != CRYPT_OK) { + return err; + } + + static struct { + const char *str; + unsigned int integer; + const char *res; + } tmp_array[20] = { + {"78BE2B0513EF6D8DA938BE94E1798D", 1912879528u, "78BE2B0513EF6D8DA938BF06E5B335"}, + {"9CE6ECE41EE8D0C6C1DB1B7DF79C15", 37203308u, "9CE6ECE41EE8D0C6C1DB1B802F4981"}, + {"F02359AD5F68582EDBCF37991698F0", 2020185834u, "F02359AD5F68582EDBCF3811802FDA"}, + {"BDCFF6CF46CF044C006C7D29F8E191", 3150062353u, "BDCFF6CF46CF044C006C7DE5BB04A2"}, + {"B13DE33B39ACAFF836E658EB6BA917", 4100301709u, "B13DE33B39ACAFF836E659DFD14CA4"}, + {"9CD3710925545E9EB4759AC910BB34", 2444148406u, "9CD3710925545E9EB4759B5ABF79EA"}, + {"C2542F27B923E97B853D9642D1E3BC", 1209618026u, "C2542F27B923E97B853D968AEB3226"}, + {"9B22C19322DB458E913D951927DF8B", 539548887u, "9B22C19322DB458E913D953950BC62"}, + {"18252DE0D0680A46C0F665A4C38BE8", 796489082u, "18252DE0D0680A46C0F665D43D0162"}, + {"4D69CB0D5DF17584988A1530F114BE", 1420558864u, "4D69CB0D5DF17584988A15859D16CE"}, + {"E3BBB7102229B645755AC3D7E57A13", 816322096u, "E3BBB7102229B645755AC4088D9043"}, + {"488432BD3613670EF6B188B46B2BE4", 2256072767u, "488432BD3613670EF6B1893AE41C23"}, + {"F24239E03FF801B58D117D0E4B82CC", 3020577677u, "F24239E03FF801B58D117DC255DE59"}, + {"58253EDE625CA5679DFAD78812A94F", 2888525486u, "58253EDE625CA5679DFAD8343E0FFD"}, + {"E80953D6F4751CDD6BAE174F4E4BF4", 1860846378u, "E80953D6F4751CDD6BAE17BE388F1E"}, + {"AB55B98542F6DD82207C38CC1A3186", 2785552020u, "AB55B98542F6DD82207C397222581A"}, + {"27650B8E53B733C8E673087E99646A", 2686262100u, "27650B8E53B733C8E673091EB67FBE"}, + {"3458536138CAF2BB856CA11792CD69", 2938349192u, "3458536138CAF2BB856CA1C6B673F1"}, + {"BF656E0EA483A34FF694AF4B8149FD", 1514764810u, "BF656E0EA483A34FF694AFA5CAC407"}, + {"51E217AFD00ED287E85236E81A32C6", 4042393042u, "51E217AFD00ED287E85237D90C3898"} + }; + + for (i = 0; i < 20; ++i) { + mp_read_radix(a, tmp_array[i].str, 16); + mp_read_radix(b, tmp_array[i].res, 16); + mp_add_d(a, tmp_array[i].integer, a); + if (mp_cmp(a, b) != LTC_MP_EQ) { + err = CRYPT_ERROR; + break; + } + } + + mp_clear_multi(a, b, NULL); + return err; +} + +static int ltc_test_sub(void) { + void *a, *b, *c; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, &b, &c, NULL)) != CRYPT_OK) { + return err; + } + + static struct { + const char *str1; + const char *str2; + const char *res; + } tmp_array[20] = { + {"843B0A08009ACE5CBE73B9B9B2A565", "B9D52A966F2C1C27D23F8BDD1D8A53", "-359A208E6E914DCB13CBD2236AE4EE"}, + {"D131433C5200AEAE6560A8A2F665CA", "85385C60207B171463E135E09892D7", "4BF8E6DC3185979A017F72C25DD2F3"}, + {"4DD65F5C02965716C96260E6F7C0E3", "984FADDF868220BF8346AE350FBE8E", "-4A794E8383EBC9A8B9E44D4E17FDAB"}, + {"3509DA0ED0177D666D8E9DF07C4AB6", "13C4B40F5F22C78411E42CBE6A156C", "214525FF70F4B5E25BAA713212354A"}, + {"37951D81A2CD204117D96DE2253E1E", "DC656CE25B647B2C8DF8B369D7CD60", "-A4D04F60B8975AEB761F4587B28F42"}, + {"50E09E18893EB0EC66C709595E8532", "72428A25C1AD51F12EED2E9DCEB36C", "-2161EC0D386EA104C8262544702E3A"}, + {"23E6DFB591FBEC4421E589ED2DAF9D", "436A4D14A71FB772C5CBD22D4FBC7D", "-1F836D5F1523CB2EA3E64840220CE0"}, + {"1B297841A5158284976987C04EEEB2", "1FC466636118646CCB6ADBE7679CC0", "-049AEE21BC02E1E83401542718AE0E"}, + {"8D46CF02736C2A5C3AAC49A3EFAE7E", "26C34AD1C3F3066222B014807C373C", "66838430AF7923FA17FC3523737742"}, + {"F70A82D504045B32F51ED0806DDDDC", "59B8529A6FBB742DCE086F91C44078", "9D52303A9448E705271660EEA99D64"}, + {"4C25D00BFD5E237A24F0A2A4D258BF", "2B715FD6000671FB437B5BE40BC326", "20B47035FD57B17EE17546C0C69599"}, + {"37A1B4908E8F3675D0E8F4847647EB", "9F118CA253113864177567CB3D66EB", "-676FD811C48201EE468C7346C71F00"}, + {"4A8B21FAD33051C069D34CEE9191A3", "6A3B2C0422E11AF8C8341A868E8339", "-1FB00A094FB0C9385E60CD97FCF196"}, + {"B23F449A7CFBEF420A21770D998415", "2BB663FB93175AC5847E5621AC90FD", "8688E09EE9E4947C85A320EBECF318"}, + {"9DB472876ABA7160D68B26C5146C10", "9EDF8BE01934AA1A04F074B16FE491", "-012B1958AE7A38B92E654DEC5B7881"}, + {"BE618780C31DA411E911DFC7A63B99", "CA3A3CE473F67B0842D464E7F93739", "-0BD8B563B0D8D6F659C2852052FBA0"}, + {"4DC88256DF0C01EA0D04FA97D3ED5F", "79591A3A73B25C7309C814361C941D", "-2B9097E394A65A88FCC3199E48A6BE"}, + {"C722C7EA75752D260DAA59BF27FC79", "BF3C9A11FBB551FEBC439AF851DFA5", "07E62DD879BFDB275166BEC6D61CD4"}, + {"98D36489C57AEABD9DEDD1FCDCE33C", "752D50ED4E379CC5A7571C841C1FBF", "23A6139C77434DF7F696B578C0C37D"}, + {"9BC66E62450D9C3DA5B02D72F8363A", "A5F3B1325E5964FF153FD9D880A92C", "-0A2D42D0194BC8C16F8FAC658872F2"}, + }; + + for (i = 0; i < 20; ++i) { + mp_read_radix(a, tmp_array[i].str1, 16); + mp_read_radix(b, tmp_array[i].str2, 16); + mp_read_radix(c, tmp_array[i].res, 16); + mp_sub(a, b, a); + if (mp_cmp(a, c) != LTC_MP_EQ) { + err = CRYPT_ERROR; + break; + } + } + + mp_clear_multi(a, b, c, NULL); + return err; +} + +static int ltc_test_sub_d(void) { + void *a, *b; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, &b, NULL)) != CRYPT_OK) { + return err; + } + + static struct { + const char *str; + unsigned int integer; + const char *res; + } tmp_array[20] = { + {"C18E9E9ACEBB4F6C9315BAF053D69D", 2638101586u, "C18E9E9ACEBB4F6C9315BA53159A4B"}, + {"0D4F03475A07A056E912773832DE6B", 3472730280u, "0D4F03475A07A056E91276693535C3"}, + {"5DC471BB0FD6D53F040B4DCA9CDBE7", 1191140014u, "5DC471BB0FD6D53F040B4D839D8139"}, + {"819E71427DA2FC02A41B4FFC875F1C", 3609952152u, "819E71427DA2FC02A41B4F255BDF84"}, + {"31C7683D9EC2E22F5C0468DC805B3F", 2513589668u, "31C7683D9EC2E22F5C046846AE059B"}, + {"503F8DD770549DBA1324D2D39BD6C9", 423448098u, "503F8DD770549DBA1324D2BA5E88A7"}, + {"2ADFF9623F7FF41F45CC3E4EDDA88B", 1912548955u, "2ADFF9623F7FF41F45CC3DDCDE7A30"}, + {"49E7FD71ECCE474E88CF204684F1F5", 3912730988u, "49E7FD71ECCE474E88CF1F5D4D6889"}, + {"DCB318D38C9F3E0F546BBACBF335AB", 2393714618u, "DCB318D38C9F3E0F546BBA3D4605F1"}, + {"9DC89C75395B76827DA4E75DEDA9EF", 238923757u, "9DC89C75395B76827DA4E74FAFFA02"}, + {"4D5EDBE5DB8BD56CE37F5B9521B38E", 3908550119u, "4D5EDBE5DB8BD56CE37F5AAC29F5A7"}, + {"10DAFA895E8FB0C24D4D87AA3FB504", 866824364u, "10DAFA895E8FB0C24D4D8776950458"}, + {"72049DDDB654335017831DB7C28C70", 3103619117u, "72049DDDB654335017831CFEC51443"}, + {"C0BD90EA333EA0DDFC054B951F8C91", 4139013158u, "C0BD90EA333EA0DDFC054A9E6B386B"}, + {"3B35674422A4126FA7C5C9B93ACBEA", 3855630932u, "3B35674422A4126FA7C5C8D36A8996"}, + {"B9C8C7A0604D9369BD879A51903A1A", 3736267496u, "B9C8C7A0604D9369BD879972DD4F32"}, + {"7FB12C7F45FCA325257665EBAF1CC3", 2157346092u, "7FB12C7F45FCA3252576656B189F97"}, + {"9626C3F775690D606C0FF3CED39239", 1454912899u, "9626C3F775690D606C0FF3781B5CB6"}, + {"4649A1BEB3EAB48A4962A5D940F672", 3521305441u, "4649A1BEB3EAB48A4962A5075E1B11"}, + {"6DBA08437449C09F277CB24405C236", 1272246752u, "6DBA08437449C09F277CB1F830D056"} + }; + + for (i = 0; i < 20; ++i) { + mp_read_radix(a, tmp_array[i].str, 16); + mp_read_radix(b, tmp_array[i].res, 16); + mp_sub_d(a, tmp_array[i].integer, a); + if (mp_cmp(a, b) != LTC_MP_EQ) { + err = CRYPT_ERROR; + break; + } + } + + mp_clear_multi(a, b, NULL); + return err; +} + +static int ltc_test_mul(void) { + void *a, *b, *c; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, &b, &c, NULL)) != CRYPT_OK) { + return err; + } + + static struct { + const char *str1; + const char *str2; + const char *res; + } tmp_array[20] = { + {"B70C24FB5F7836F873D25E5915191F", "797F9003DBE1E68F01AF74B6431C91", "56DFF37ABFFEED6F27260AC9E146C586317213373CCBBA7D5C9C60CF9E8F"}, + {"0B965400E39B8276832A294D06A756", "CF8F44D35F14F122473289C57F32E8", "09650A03240F176192E3D5508039E5AFB2F608ED441211F5F4914C6071F0"}, + {"5850B4D68897F12B32C83AEE7BB33C", "F7B96AFE992CB0DCF0F906AD58E172", "5575D5B6EC9F37DF6826D14ECE13F369D52E6E5039B9068017E6143D8CB8"}, + {"3DA1E7A6E0F833AE456C5F6A102FE2", "45982F1859F85E280F74CC123EAC83", "10C146E81C16E94BD6E5934EBD9A6D0F95245724AD79BFBDF377A33058A6"}, + {"D9AE5BBE2BDB76111F67C603D0E8AA", "25E59048FA21458DDAC80508E17E15", "203966EAAEC949BF07213EB4B5A68F074C0D0BA4CEAC4D6C3652F010C1F2"}, + {"2CE03008981952C91C996C7FC38623", "E70DB18FB2EB22BAF359DABCBCBFF1", "2880B1DA637C723BC2F902F067857E2678BAE683F32B8B41315D5DD963F3"}, + {"0179DE431A0D4552966DA9E565A1BC", "130F72055F3DE041426CD62691BF3D", "1C224B4DC550A57B98694E4F1076512814C5EC992F509A6B5D005ECDCC"}, + {"5EC49F6E7ADCE400B1C953D82ECB77", "DD7DAFAEFF50D6304394EBEB412CB6", "51FE44AD6A27594F89E250FC546EC868F62DC52683FD3376F5A8A2741A9A"}, + {"BA1429C4210CE0C6FFDB8CDB69B74A", "BF7062EB6EE5580669BE4A4BEF0264", "8B26BBE27391DAFF4F2957ED7CAD7C6B7DEE31143533C463948554D02CE8"}, + {"A9C5E20A0D3E5B4A348214DC5C1E0D", "DAB79A667097874DAC3C0557A8FBA2", "910C45561DF3BDA0D32F756CA4F7890B976E96723707E3EC522CE749C33A"}, + {"79B7E68C50FA2E35C48DC43D28746C", "30788DE46BC9A6EDC79DCBABBAA15A", "170BCCE545F939A0A00009627BF03661843F380C6BF1641F4440ABE8D9F8"}, + {"45FB9E2127742B26EC4E395F823CCE", "3C135492047A1E0177C051E972FB38", "106C41DAFC51882CB559E963757C454A68F0C41C1CBB396F2BB627D74710"}, + {"E13929EC91D0797C7DA0B969F5B716", "453CE8EBD86B738DE213E4E4030983", "3CE9FE9DE29E01D771A247D73E450F71E2ED029285CD7E548A23996E7642"}, + {"FF1DFF1FDC130D7DA1F1C19218AA1C", "C9C3143A50E2C394FBA58F559987BB", "C910F551CE653DA1C49271A76122DA2899EE40D37D4F68DA3F4DB0750674"}, + {"31C02B09E12B7DC76D630709F3CB14", "5120DB0A30F2138C63C8BB1904A5D2", "0FC43034E1511DC5E81320EB5B53752D1E42886E87D5891CB3706C307A68"}, + {"506B49B08790C08D7C7BF8BFC0134E", "67A1C15317AA830D505F627F806BCB", "208DFADA5B56ADFAFBF9DC509545F0E0882AF8B6E1DE4A18C5DEAE60E8DA"}, + {"E93DF474B6786F79EFE3B433A844D2", "02F8307200C360B023A811F1D18244", "02B49C11369C7603B430191BD602EF5C55438976E0AD6425F5350D16EBC8"}, + {"EC6A3360BB3548AB9C49B50661825F", "2915CF2E849FE89A7A2B468AD99130", "25F126458A05C606DC5257211386F6D6C0E359F0479929C5EE7725A740D0"}, + {"B24690D77954E2E0DEEC97F0609031", "5ED75F4B754EB4D127C4EF06FAE9D3", "420BE4CF7FA1865E0A066C6D145347B1ECB3A2F943AE2A196E6FF8AD7163"}, + {"29583BF1C2087C2620152F710CDA2F", "1CADD60FCCC59ED9CF62CC21A56781", "04A1B9C142F2E2FFF17E8AEAD1B845914BA5A7451CBC289C2440D28DDAAF"}, + }; + + for (i = 0; i < 20; ++i) { + mp_read_radix(a, tmp_array[i].str1, 16); + mp_read_radix(b, tmp_array[i].str2, 16); + mp_read_radix(c, tmp_array[i].res, 16); + mp_mul(a, b, a); + if (mp_cmp(a, c) != LTC_MP_EQ) { + err = CRYPT_ERROR; + break; + } + } + + mp_clear_multi(a, b, c, NULL); + return err; +} + +static int ltc_test_mul_d(void) { + void *a, *b; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, &b, NULL)) != CRYPT_OK) { + return err; + } + + static struct { + const char *str; + unsigned int integer; + const char *res; + } tmp_array[20] = { + {"1BD7F2599CB558A8145A1A149C1568", 575098425u, "03BA6F961C96CFC50EB59013F47437E51E7428"}, + {"5463DDC2D243CCB976F414641FEB5A", 1093369850u, "157BB244ABA6BEEF7320E34E1965B3FF0B7BE4"}, + {"477CF56986A9428600CD66DA961D7C", 1266272257u, "15139DCFD08BA31B7634815E2073C3653AFD7C"}, + {"F47FF633460FBBC624D35BC5EFFC13", 2388753994u, "87FC17AA6274AD6C0D78FE643D61B462A3377E"}, + {"E1AF86DA155390D8E31AE850A11578", 3694383486u, "C220868AA9427ADFF6C2BA2A5166B598B78910"}, + {"60B3F732E32749D57704DD767750DE", 2762944078u, "3E3576E0628EE97A7E6854A06BB22208A487A4"}, + {"8E3B61227F361FA2667A3B9FB4C653", 1205681345u, "27ED62F491982551F0D64782AC2272006BF893"}, + {"EFBB5AC4DC54780101A6343FC426BC", 2117046459u, "762AC19B0F80104EFC3354E4AC0C1C8E960B54"}, + {"4D0B949E45144CF3B852C60E245793", 2679242357u, "300FC2E4C21553B44A9ED68316B0115F22E02F"}, + {"9D1418CF00E16EF07F3736132318D7", 2876840455u, "6936BB0A557FB368001477B66D7D9A711A83E1"}, + {"6C78E6B7508080DA7E4083D6FF8A2F", 642621302u, "103AD62DB21C7D461BB8A619D538AD5ABFE2AA"}, + {"8FC380E176D2DE00B72EDCACE02A82", 1969400383u, "41EBC25996504C93954FA69DAFB4591728C9FE"}, + {"BD1D3BD7DBB35116C8F8734BDBD4B8", 1471750368u, "40CDB1BFBBB70D7AFECD77C90155851BE92100"}, + {"878CE8412A45FE444F3900BE5D66CD", 3931331339u, "7C12EF2FC761D3EF92F3FF41E9CEF3180549CF"}, + {"86EEA9F5CDCDCBA7FB6CD363909C91", 921679158u, "1CF4B02DBA6730727B43696354DF0500928B96"}, + {"7D1EED36B38F7F338EDA782662AC1E", 3360147505u, "61E33EBEA2B20BED08BEECEE556AD19BAC61BE"}, + {"BF41AB1D5134D8F695581FEB5A2905", 1132736647u, "3270F1E613156FB823C7B7D455682F79D091A3"}, + {"5710600F57F3039861C5077A586EEF", 691229558u, "0E03140808D5B1937332186307C77F71579F2A"}, + {"1636FBCE02F890343F2741286FE037", 1766339541u, "0922D13DC112560DFA2340D146E6B28D3882C3"}, + {"2EF9D89C5D1790A70F27BF3469CEB0", 3030733559u, "2126028FE8AEA6951066CB1971C5CB6DBACBD0"}, + }; + + for (i = 0; i < 20; ++i) { + mp_read_radix(a, tmp_array[i].str, 16); + mp_read_radix(b, tmp_array[i].res, 16); + mp_mul_d(a, tmp_array[i].integer, a); + if (mp_cmp(a, b) != LTC_MP_EQ) { + err = CRYPT_ERROR; + break; + } + } + + mp_clear_multi(a, b, NULL); + return err; +} + +static int ltc_test_sqr(void) { + void *a, *b; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, &b, NULL)) != CRYPT_OK) { + return err; + } + + static struct { + const char *str; + const char *res; + } tmp_array[20] = { + {"A2C775A89A803C4C073409AE54ED6C", "67810C5185BE0BF253FC3A4E88901DE27C7BADC92F6D550C20837B112590"}, + {"73DBD800EC5B4BFBBFCA9B00BF6862", "346F40DC1C2FF953197B743509F5E969C29EE02844C1E6BF9DC8ECCBC584"}, + {"83B152D9242AEBD3E6E3BD04BDF9B3", "43BEF59DE617C40ECE46010B61E0456971A8531D9B94A910A1163DDBB329"}, + {"CC40A4C991E9B3B0279FC244B4E21A", "A2F716F40F684CE4799ADDC7AE14CDA41DCF7D580F21895F93548C41EAA4"}, + {"0F74F6636E2C202AE414C6C97F0618", "EEEA4FDE28421D60F664E40865D67C06FC145E081AE2C9E3B8BBF52240"}, + {"F3AD2CB5D2732A4771BD21047E7A0C", "E7F23806A3141365A0E043993ABEDEEA66852234B82F4F7D6164BDFF7090"}, + {"47C6A532CE28CFF8B39552AD495C28", "141FC9C6238C1253726028B28D56D8BFF6C57245583F3D81D533BFFCC640"}, + {"84018C7ABF28CF9F4F90E46748B926", "441198E0FB2E105D4E0619DBDE9E4287DCE8B771204D6CF425553F47F1A4"}, + {"695FAB90CAC620EC25752C3BB7554B", "2B5F9E7D8EC7C6D7957BB4401A42512EE66C22A6153B1897E4639FA4E3F9"}, + {"E949A908C81AD0E919F4A39ED34A6E", "D4972AE3D2DF8813FC1ADB6E5EE70D5B681FB7313CD72EF7F6578EF7C744"}, + {"F27D771F6223E4109D24542DE5C7BC", "E5B172B4E19FE35269AA5263B0577499D29323FDFC4543CA89D70A2DD210"}, + {"7D24C50F530C8FD2152C6ABFB44EF5", "3D2CEDB8FB1A36B7C786A9D219B888E03D186F71513E343627B4B6E23679"}, + {"CCE4432C2D208BDAF1BC4988BE0BE8", "A3FC9696203C681CA39BCFAECDCC782055533ABE25FFF1BA040C2CEDC240"}, + {"29ADFAD58DAB3A96F8427C4D3B8E96", "06C9309561C81D09075542D9577182DF7603C950C2A1A9245AF1448EBFE4"}, + {"0A841BB426D8C241A7B42D4B05DCF7", "6E9656A7D07DADD47F1C4048BCE469F32E1D184BBB6D0976711A5F7651"}, + {"D15F3D3E75ED35806316ABEA49314B", "AB3CA56E7F8FAAD9B7CC57A465C655F1B2865F63ACAC88ACA13C4243CBF9"}, + {"C5F1577EA1D09449DB254829A183D8", "990D542EBF5EFF9052BA2D5F3444D57ABDB30552B9A8E54BBBA24996C640"}, + {"B982E44741974AB91F8491A0C17D49", "866E70DBA0BA48526364FD4D1C0EC301451928FDA2C2E303A38B65625ED1"}, + {"AD0D423E1AE00B44EEE2D1AE9BA60D", "74FAEC37BBC59EE8DD06195DADBCF3E203BF563542C70A9809962B72DCA9"}, + {"5771AD736F3A5BF27B9BF58F3B76F8", "1DDE765F0B071465FB1D208C0CF71BD171AA41064B5EAC5583691D999040"}, + }; + + for (i = 0; i < 20; ++i) { + mp_read_radix(a, tmp_array[i].str, 16); + mp_read_radix(b, tmp_array[i].res, 16); + mp_sqr(a, a); + if (mp_cmp(a, b) != LTC_MP_EQ) { + err = CRYPT_ERROR; + break; + } + } + + mp_clear_multi(a, b, NULL); + return err; +} + +static int ltc_test_div(void) { + void *a, *b, *c, *d; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, &b, &c, &d, NULL)) != CRYPT_OK) { + return err; + } + + static struct { + const char *dividend; + const char *divisor; + const char *quotient; + const char *remainder; + } tmp_array[40] = { + {"34B3716544C969D558DF9921765ABE", "8DDC2C232E1C6B18613C251E815C67", "0", "34B3716544C969D558DF9921765ABE"}, + {"A8E160DF073185B48FEB2ABECEE412", "3E696361E8D4AD8E4B7121AB0B0A5A", "02", "2C0E9A1B35882A97F908E768B8CF5E"}, + {"C2810789FFDDA612928BEE9B53A5F1", "C925F4B8091CB2EE7B7138837D536A", "0", "C2810789FFDDA612928BEE9B53A5F1"}, + {"BF2485CB9DE74D013F2DEBF6B056DE", "1F0B3932669B0D9E291CBECD95035E", "06", "04E12E9D3644FB4C488173253242AA"}, + {"9AE071FF783DEB6FDEA63090201138", "DA43610E9841CC69DEED6E889F75AD", "0", "9AE071FF783DEB6FDEA63090201138"}, + {"133594B769AA2953C12E6A03534DEB", "99A7BA5CE77B7124B86A6A92A54F69", "0", "133594B769AA2953C12E6A03534DEB"}, + {"F64EF511CAD89829C0C54A628B20E9", "A3C10CA955539E51A564B7BBD2FF1C", "01", "528DE8687584F9D81B6092A6B821CD"}, + {"F7755D0D584903C73E505BC9C304BB", "EE7BF8625FA68CCD6315649B97165F", "01", "08F964AAF8A276F9DB3AF72E2BEE5C"}, + {"D21C3238D7FC3A3D8535D59E6EA7F6", "F0969F901C475ED8E12BFEC3EF8C15", "0", "D21C3238D7FC3A3D8535D59E6EA7F6"}, + {"AD14B8996880786D492769F3E72214", "2360C3DF341C88D61A52A0D943E5EF", "04", "1F91A91C980E5514DFDCE68ED78A58"}, + {"57F23562C0E4F840822EEA48E7E555", "7AFC39879BBD85CA877CF74F6676E0", "0", "57F23562C0E4F840822EEA48E7E555"}, + {"9AD6E642F9D9174B0E6D56440EF818", "8D4A205D932FF73E272C1D9FBD81E9", "01", "0D8CC5E566A9200CE74138A451762F"}, + {"23F24A17237F481FBA123F42C17D97", "0A8A6AA1F7AD3BE58469815A3AAEF5", "03", "04530A313C77946F2CD5BB341170B8"}, + {"73149B971FA0D65B2C3BA65A09E25D", "66E0B25E16BFF09594BBD8A242472B", "01", "0C33E93908E0E5C5977FCDB7C79B32"}, + {"820A585C843F5BCC07D8ED7204D3BA", "8E10E29A6AC804F1CA6F01CBD1B3BA", "0", "820A585C843F5BCC07D8ED7204D3BA"}, + {"7898E6F68DDDD24A9FBA576DAC458A", "CD9DFA5F4B69BB674C64BE761E999D", "0", "7898E6F68DDDD24A9FBA576DAC458A"}, + {"61FB446B58B6DB80885F3DE7E51CC0", "960E7EC6DA1BDB02324D74D8F9BE3C", "0", "61FB446B58B6DB80885F3DE7E51CC0"}, + {"0C212FF4184DC212D40FD563DF4E41", "2C396013D89785081C6F6E9876CEDF", "0", "0C212FF4184DC212D40FD563DF4E41"}, + {"5B0AFB27FB2481E8B4AD8039C1A468", "6AC8D9BC6F9BAB085F9E607CC1353F", "0", "5B0AFB27FB2481E8B4AD8039C1A468"}, + {"5A2F809AE8CA57881DCFF552B1CB32", "EB812763D156258E4588D1748D2E6F", "0", "5A2F809AE8CA57881DCFF552B1CB32"}, + {"97D621C6BCFFA9077C7651BD76B57C", "016891D8AEF0F8890B8DA8DD29", "6BCD4F", "261852D45D37B5BC5D1DA0D5"}, + {"3CB1898441C5080C52C4E118CBD077", "080BDD0976B3BCED6C4E5DC280", "078B01", "0532025DCF45B5E45790528DF7"}, + {"A66210FE2E0B5F1A0FE1B2E2606AD3", "0290CDB75DE23EB5C1B2EC4ABF", "40D9BC", "026F343DF85B847BB681BD9F8F"}, + {"DCAE3E5B65A8D816AC21F84D14B026", "0239A027C23AE867374F6B008A", "632D87", "0170D6C5304195447667312560"}, + {"9C972AEE037E94D09644DEA8779794", "0D46FEBB0B42F696A2B635399D", "0BCB38", "055E7CC56C283476811E647E3C"}, + {"3021DA735E9C7220A9933ED7A2FD80", "04283B6EEB9AC18837A5F178FA", "0B9402", "0202A7E2D22E02357FBF11838C"}, + {"E4B38CA90CED65076E9D97F81F53E9", "08A29FAD617DDC2350FFD2912D", "1A7C10", "058B3015FAF257313B3E127519"}, + {"208349E03BEE7EE66EE3B9C0BB10B3", "0A7F8B7A8076D625BE18C35381", "0318D4", "BDBD0C75F85385B0F4A2D1DF"}, + {"B2E0644CA645402DA854145BFD4F8F", "05658405ADDDEFDC1ADA8E3621", "212580", "BA67B1522B7438BB8CCE7A0F"}, + {"D9A26DC52E42814AE2A8272521AC1A", "0A550766D35CB9A8378902973B", "151056", "094EEDE679BD726FB88CF82E48"}, + {"29CAC2304BD7B52FD08E854AD8B205", "04C1DAA0182DC27523C576E08C", "08C8F0", "04A5816F36B4E09F004798CEC5"}, + {"1CCBC1716D727AFCDE80E512635F1F", "0B6F10AC4DA82453ECE7FFEEDF", "0284BB", "015ECC3AC5C7353B37C586E63A"}, + {"DB05A44030099338B12CAC699A9AD1", "07DCD6E18A099E265FC4CF16A0", "1BDB22", "034F25FB559AC264BFBADEB991"}, + {"5E49C72E7E99E315341B4D6F4F62B4", "0B477411535103EC79AC847B69", "085C0A", "08232173651E43C0693A80D49A"}, + {"799C6D32B77E5E9AA8862E9AD2605D", "09CD814A7061817DA1919C1C2D", "0C67E2", "07445BFDDB8938C8A4ED8F65A3"}, + {"4D72D5B4BACEA1D203C90612D0DA0F", "01C6C53DF32BD52CCDE4087CFD", "2B98F2", "0149A57FED494FE1927A157AE5"}, + {"0D2B2B9DA9FC051D0E007573C44577", "096658B56B9E975AD155A55863", "0166A4", "05FF21434BDB1714955C3D340B"}, + {"8E34E3BCE8A2449B92A555E806CA0E", "C7EDACD38373F4A35A9F1CB9", "B616F1", "3AEF4D69F840E0A5803ED9E5"}, + {"CCEA69D7BB967C5A6A5810BDC956EE", "01E3BA5E49160DF407BF4AF00F", "6C7233", "B4C8F437CBB293B8FCA0D5F1"}, + {"1A02864421DDA61BA4BCDF7F09FC79", "05AF90A1CD38638813408DD738", "049314", "01F8B780AE6C6E0B15A4800419"}, + }; + + for (i = 0; i < 40; ++i) { + mp_read_radix(a, tmp_array[i].dividend, 16); + mp_read_radix(b, tmp_array[i].divisor, 16); + mp_read_radix(c, tmp_array[i].quotient, 16); + mp_read_radix(d, tmp_array[i].remainder, 16); + mp_div(a, b, a, b); + if (mp_cmp(a, c) != LTC_MP_EQ || mp_cmp(b, d) != LTC_MP_EQ) { + err = CRYPT_ERROR; + break; + } + } + + mp_clear_multi(a, b, c, d, NULL); + return err; +} + +static int ltc_test_div_2(void) { + void *a, *b; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, &b, NULL)) != CRYPT_OK) { + return err; + } + + static struct { + const char *str; + const char *res; + } tmp_array[20] = { + {"5A880BB7F76DC5688D4961AD4B0BBB", "2D4405DBFBB6E2B446A4B0D6A585DD"}, + {"B30CEAD3746512B73C02040D6844DD", "59867569BA32895B9E010206B4226E"}, + {"05DB6833C3479A58D9410EB100604E", "02EDB419E1A3CD2C6CA08758803027"}, + {"3AB4DDFD9E96115DE5EC532779B3C0", "1D5A6EFECF4B08AEF2F62993BCD9E0"}, + {"077B7029442F3FAF9AA2BB9DE038BD", "03BDB814A2179FD7CD515DCEF01C5E"}, + {"F32F7DF33B121894BB6CC25806C502", "7997BEF99D890C4A5DB6612C036281"}, + {"379F60C43D4519E9EDA846A1521023", "1BCFB0621EA28CF4F6D42350A90811"}, + {"608391B5AA4812C9B069D3196A223C", "3041C8DAD5240964D834E98CB5111E"}, + {"2638BE7E9F60494869EA28F0F162BD", "131C5F3F4FB024A434F5147878B15E"}, + {"5B976DF95542035BA953A7EBA4DCC1", "2DCBB6FCAAA101ADD4A9D3F5D26E60"}, + {"CB0513D358BA0F11AAF816126E686E", "658289E9AC5D0788D57C0B09373437"}, + {"64236DDE7513F93F42A570AC2DDFB1", "3211B6EF3A89FC9FA152B85616EFD8"}, + {"E37C38BCBC2E9ECF0DCE094DEBAA75", "71BE1C5E5E174F6786E704A6F5D53A"}, + {"08EE28D554EA0A6022C1B4A51CE8BE", "0477146AAA7505301160DA528E745F"}, + {"3C02126DEDDA0343822F36173B6B17", "1E010936F6ED01A1C1179B0B9DB58B"}, + {"89A58F70A9F2A394AA91501A893F18", "44D2C7B854F951CA5548A80D449F8C"}, + {"72F6E05E41C37E0E902D60107C28B8", "397B702F20E1BF074816B0083E145C"}, + {"0A91255A0D7D2E063E22C57F33A15C", "054892AD06BE97031F1162BF99D0AE"}, + {"EA16035028F0B8611B44EE12F7A294", "750B01A814785C308DA277097BD14A"}, + {"B10977732ECAF77EFAF6B84C0EDA94", "5884BBB997657BBF7D7B5C26076D4A"}, + }; + + for (i = 0; i < 20; ++i) { + mp_read_radix(a, tmp_array[i].str, 16); + mp_read_radix(b, tmp_array[i].res, 16); + mp_div_2(a, a); + if (mp_cmp(a, b) != LTC_MP_EQ) { + err = CRYPT_ERROR; + break; + } + } + + mp_clear_multi(a, b, NULL); + return err; +} + + +static int ltc_test_mod(void) { + void *a, *b, *c; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, &b, &c, NULL)) != CRYPT_OK) { + return err; + } + + static struct { + const char *str1; + const char *str2; + const char *res; + } tmp_array[20] = { + {"E3854B159468078634F689A36303B2", "C376E097F1E12B97976525356B445D", "200E6A7DA286DBEE9D91646DF7BF55"}, + {"-6C09610D5DC53AB7C02CB4FB2B35B2", "3F7ACCCA4CF4104CA8082C84A21ACF", "12EC38873C22E5E18FE3A40E18FFEC"}, + {"-6F9FA58761604803FCE51EE165D8BE", "FFA90B13EE050B46CA46CEA0882058", "9009658C8CA4C342CD61AFBF22479A"}, + {"09F46F62AE90B7461205EBDBF9B1D7", "2DE007FF22FAC64717E73AD76341CA", "09F46F62AE90B7461205EBDBF9B1D7"}, + {"F10B4B174F956B3D3D724BF99B0D11", "04D0011BAC20ABBED066FFDA3DDB92", "6B13AFB133DFF889545359862A8D"}, + {"-4BFB30796355295FAD0F4649078000", "3E31D9EEEE26839634F965AF4451BD", "3068836478F7DDCCBCE3851581237A"}, + {"DE08ACE5D11E8763AAF3E9402A181D", "23BCC9D78CBFC8FD664F06EDC485F5", "079BF1D8849FD1734519BFAD8EF45F"}, + {"6BA5A652551A2357AA38E1012FA32E", "0E910E03D083116EB81B3ADE41A3BE", "05AE4437A184A950A17A44ED6428FC"}, + {"99E01CB40C8B9CB0B19266398FC5FE", "B57CA666A503B9B08B4B66487D5EEC", "99E01CB40C8B9CB0B19266398FC5FE"}, + {"8D13215E7CD1F97B352F8688740F", "E45732291F643B1694BD6D4F55A8F1", "8D13215E7CD1F97B352F8688740F"}, + {"-BE3FA72CB3FF65E58E6C66BCA775AA", "734D8B0ABD85DA1642778AB096825D", "285B6EE8C70C4E46F682AEA4858F10"}, + {"EF1293B80E85E9AD0C73B17D5A841F", "5DA159448258B6547BF55610C7B343", "33CFE12F09D47D041489055BCB1D99"}, + {"-13659AF0AC5475ED7CC529539A3172", "3EB8CF026C1AC5C03F13FC826E51", "3425C01573E7DE96F115952847DE"}, + {"-A894D3A8F59FE4303E62FBEAF60745", "408AFE241749D9ADA9AD6015B945EE", "190C26C3503DA8D8BEA5245635CA85"}, + {"-8AAA567C1780274E935547E7731712", "1789B298B57BEC30D2CB0EDDCB278F", "028FD918296761D65D6D114B4FD648"}, + {"-7784002504D12DCD97C569E855B849", "A066FC7AC5E3954A98E9A1BF21DB43", "28E2FC55C112677D012437D6CC22FA"}, + {"-30382E761172600233AE48680CE502", "D4628C20B4DFFE5B8D09A7593D7B95", "A42A5DAAA36D9E59595B5EF1309693"}, + {"EC9C73E6143E6FF4A7A3A37C8B0AB7", "A4D92E66607D03601329F0AF0C1224", "47C3457FB3C16C949479B2CD7EF893"}, + {"-775A685CE500ADD1C67AD4862EC70E", "93A40E020FF434C4FCA7CDB9FC1C66", "1C49A5A52AF386F3362CF933CD5558"}, + {"FFFFFFFE00000000FFFFFFFFFFFFFFFE000000020000000000000001FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE000000000000000000000001", "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", "0"} + }; + + for (i = 0; i < 20; ++i) { + mp_read_radix(a, tmp_array[i].str1, 16); + mp_read_radix(b, tmp_array[i].str2, 16); + mp_read_radix(c, tmp_array[i].res, 16); + mp_mod(a, b, a); + if (mp_cmp(a, c) != LTC_MP_EQ) { + err = CRYPT_ERROR; + break; + } + } + + mp_clear_multi(a, b, c, NULL); + return err; +} + +static int ltc_test_mod_d(void) { + void *a; + unsigned long d; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, NULL)) != CRYPT_OK) { + return err; + } + + static struct { + const char *str1; + unsigned long mod; + unsigned long res; + } tmp_array[20] = { + {"E70306F29076E8BF7DA5D5563A0A1D", 663883874u, 87677119u}, + {"6A46A66C7F1A4E3BB3BB4B095B8082", 1040178009u, 340478028u}, + {"6880B04992C05D4803723C4A9D7788", 1690151894u, 1187732480u}, + {"265EF60B4DA40923759136BA0C0A5C", 118169354u, 31955840u}, + {"2499F1A77C3060987590610110BA0B", 2094746492u, 1078203347u}, + {"7428BC9B7B0865CF40D743D7EB2793", 2119169066u, 1933899525u}, + {"F577255475039C7594A0FD0BE3927E", 1222289707u, 105246748u}, + {"FF7B580C083B113A69C9D26AC1E7E4", 1493262936u, 683840524u}, + {"94F5905E5633CFF8479EF79D9ECDAF", 797247411u, 281286396u}, + {"5CC06683179E36144B7D921BBECDC5", 254694800u, 200091877u}, + {"E0442BF22B9707383CB5E068A05889", 2808061577u, 2553303241u}, + {"D9EB83C4FBD72087B9F63B5753AB9B", 389295616u, 248005019u}, + {"81F62BDE841DACF9065A29B443580E", 1399115832u, 328396942u}, + {"0AC8AE90729E2DEA9AFD0B25CAF798", 342230715u, 52231220u}, + {"F4BF89BDEEBD4B152B35789D85FE33", 3307757544u, 88541947u}, + {"3F15910B335BECBC56CD52D0F986C6", 2936401451u, 23755171u}, + {"6CA18D6C9F95E3054265D0E8BA8587", 3864796788u, 1506173443u}, + {"23B47607BA0D51761BE7E2F2CFC926", 508117654u, 298269886u}, + {"498F7C009D3064C661BF86CE0955C9", 3699908195u, 2374757021u}, + {"2AF9BF9678BBCB99433FD0BB8F0C81", 1445986198u, 696086091u} + }; + + for (i = 0; i < 20; ++i) { + mp_read_radix(a, tmp_array[i].str1, 16); + mp_mod_d(a, tmp_array[i].mod, &d); + if (d != tmp_array[i].res) { + err = CRYPT_ERROR; + break; + } + } + + mp_clear_multi(a, NULL); + return err; +} + +static int ltc_test_gcd(void) { + void *a, *b, *c; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, &b, &c, NULL)) != CRYPT_OK) { + return err; + } + + static struct { + const char *str1; + const char *str2; + const char *res; + } tmp_array[20] = { + {"11F5483B652452A8A306725B31D574", "3CB337210966A28859D4D7668D1DB9", "0C0AC39A0E8A2D5D"}, + {"2FDA749ECFAE13EE77B65CF600B008", "D6157DCFA1A280D1E9DA882F4B59D6", "1C169C50372107A6"}, + {"D59F612E1673F129DABF3ADBE896FE", "649AFED05BC4AD19716EC1EAEDC354", "5176DDE8DFD32C9A"}, + {"F4C3A58951DB03EADA52A1679F6F57", "2C732AD849958FFA963A8AC59D436C", "0FA412099384779D"}, + {"41E39AE0BC9702DAB374E3697C397A", "3EAD05F4D6D49444ED7FD3B877F467", "0EBA03F8BD2988BD"}, + {"224080C9D379E24F16A980C2164FB3", "5385E7D6F8EEF03F401450712ECDB7", "0C157E845FA4590D"}, + {"29ED30583FF9837A7BE7AB08B5F7B8", "828B49CB4A5314D11B724E859C953F", "0C5935720D05B2FF"}, + {"3235EB3DDC2DB08C464324C349E6AD", "4D11758748D9DBFB891C287CA13181", "0F21750CCC805F05"}, + {"4A4A1561D374585ECD29469B357C38", "BE776E11BB39CDC7AC8F60D762B1EC", "37073B0BE2CEF64C"}, + {"0790EB6AD07EDE318A7B0C0D327D54", "2D6FCB9F049D632DE35DD3F4FAACDD", "03B4A3C3C5FB46C5"}, + {"76262ECA8DC1058B93128D3E31251A", "6FDA8A9A41E502437C08C733A873D9", "D5F334CF945DEFA1"}, + {"7CBDEC5E9B145212E1CA7CE4792C42", "BBF4BCDF101B5129FE6CD442BB9395", "0BD258E676A3199F"}, + {"049100DA58844EB8FA8A41D082631A", "4E90829D6943CD2172066C3D364995", "05E88B7FB6A7C5CF"}, + {"52DF4891C2283FC5BF2B4C0B69D358", "263F188D4A79889BE03190142DF9F0", "60DAE27B72308978"}, + {"EBFC17B632BBC485B5F839BD64C3BB", "61A3B6B4DE64E00D45D458314CB79A", "0F0F5460F85EA879"}, + {"A965D7FECA7146AD777271BF5D7EF7", "87EEA99A5505C7A541F494FE012E53", "0C3608F13E901B2D"}, + {"0326BA75C1F752316F5F5274292776", "2C3E6321ADF0588A0DAFD67A93E672", "164E3A8CEA96FDB6"}, + {"3F1F03F841FD3D35CAB0FF72FC9268", "22A1136BB8FF4715124B08D56632CF", "068BE7EA8405E06B"}, + {"3B128D8EB80D83C9069B6056F1D46A", "99A43D4BEF9746FB1DFCA5CA570539", "0CE4CCE91767A583"}, + {"4A6ED7AB97AD26BDB30F9F1D08BFC0", "6CEDDF1665E68085202CF0962D2C87", "06D2E12B4C97A591"} + }; + + for (i = 0; i < 20; ++i) { + mp_read_radix(a, tmp_array[i].str1, 16); + mp_read_radix(b, tmp_array[i].str2, 16); + mp_read_radix(c, tmp_array[i].res, 16); + mp_gcd(a, b, a); + if (mp_cmp(a, c) != LTC_MP_EQ) { + err = CRYPT_ERROR; + break; + } + } + + mp_clear_multi(a, b, c, NULL); + return err; +} + + + +static int ltc_test_lcm(void) { + void *a, *b, *c; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, &b, &c, NULL)) != CRYPT_OK) { + return err; + } + + static struct { + const char *str1; + const char *str2; + const char *res; + } tmp_array[20] = { + {"1CD72AF305E2B70B00A3ACC487D9E3", "0359CF141D454BE8D43B26E5E28D09", "333140193D1D3CA50FC3437181DC93C819E8C1FF6CDB"}, + {"20887D09DAE2482ABF2DDF8557EE68", "02291E5C5FB7F049121C767A3042DE", "090C4ADDD0F01706BA3FDF56D2E4A8CDDD91974B3DF8"}, + {"5004706CBCCBC35B3CC02FBEE7B5E8", "6E1BEBD80399E1EBAD06DB5350D78C", "013654C312FA4178D29751DA90F4CE08FE25BA01BABDA8"}, + {"3AE87128D427392FDBB0A2B86AD300", "31FA43363495372DD0C48484BF9BEF", "01AD532023D117D433333D014967831FC061E32D240500"}, + {"8153AE5DD4E379AA4DD37EFA505553", "23D7ABA99A3A9C6F197F23978232EA", "8BE86E2427DF44EFD8DD45BA2C7C9A38B2470E973F5E"}, + {"0118C498DD065C7BE2801406BE9075", "33D8B113CC4FB5536E2EE4716407CA", "10D516AD81CBFCAB7D271D728CD1A123501BB0E7C6A6"}, + {"F54031D703DE3156782F557E5E7E6E", "9EA70E82ED8400C6090FA0CF454BC5", "09A0E3224A84EDB97617B54564D1001A380826E80887EE"}, + {"971F2238A502352FD6558ADB431A84", "50694BA15F239E86FEB1759F80C59E", "01A3D493E860192A9D4454469F68A36184CA594BD1B994"}, + {"1B8E61E370147AAC13D997D8B478C7", "75E9658754C26DAF691DB80E6484EE", "FD742F2BA3A9B5B2823BFD97B31E25137B83300D35EA"}, + {"1ABDBABC32A242F3BA84B5A1427431", "6EFAC7D0B0E88E0491E03E76C16A04", "2F66829F1339D655BBF20479AAD71AB8B280460DDBF4"}, + {"7C83B2627482858392C7FAD745E533", "6B69E54AE451B98064C19C305F3BCE", "037B8CA6839CFFBD34553ED766BEC120D9116B6150CC0E"}, + {"2E93D947F7EE09F099B3A9893E188A", "16FDCE15FFCCB7512980523D50B51D", "484EE59D88F34358780EECD5AB215B71B97E6504D8FA"}, + {"8983974C92490905D31EB1B2ED03D6", "17181A6C1006C2FAE360896B36FB9C", "ABA87CBC76379CD1BAB231404FF96BDCD903C5A4E1E4"}, + {"7C33272C02C76ABC1D3F346D073213", "25A45D48ED4ECAAFAFE15BA47BAE94", "01AABE733614964EA73F10907E228F584EAA63792904A4"}, + {"45D743504F0A5EF102E6F090AB710E", "056965DDE688BA88AABD02A1F901DC", "22AF9102AB7B8DD0AD3C9B28BBB93C06AB84D1521E7C"}, + {"9BB4DB41459C36C50748161723A7", "0660FCD73D0FC7FC4659DD6BD95C4E", "042D8570AC4007821C30DD4789453195F4EA6A9CD602"}, + {"2597F43F9FF991DE5E5C5BA8856ABC", "2C951665B0037C467E979D4F66CF38", "95B859FAED60907ACEB536F81D5499813EB5010FDA18"}, + {"2F811D2706123DB4538AA2AF1201F6", "15990BBD39FFD3D93A062974885AFE", "201C636CDB49FAFF9CC03983E8C7EF8E4FD4F0E1A12E"}, + {"2DC31E80DB414E320B41F01D08FBFF", "593E0F221C10B050AA81B80B76E6B1", "0123FFECE52D5FF2ACDFF86F5B7248C407C9B76A56A76D"}, + {"52E8F61C335E2AD31AC5B8831A0F87", "5885901117733ED51066035F68E350", "046AA167C4583495651796DB381FFA9C5AE21A141077D0"} + }; + + for (i = 0; i < 20; ++i) { + mp_read_radix(a, tmp_array[i].str1, 16); + mp_read_radix(b, tmp_array[i].str2, 16); + mp_read_radix(c, tmp_array[i].res, 16); + mp_lcm(a, b, a); + if (mp_cmp(a, c) != LTC_MP_EQ) { + err = CRYPT_ERROR; + break; + } + } + + mp_clear_multi(a, b, c, NULL); + return err; +} + +static int ltc_test_mulmod(void) { + void *a, *b, *c, *d; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, &b, &c, &d, NULL)) != CRYPT_OK) { + return err; + } + + static struct { + const char *str1; + const char *str2; + const char *str3; + const char *res; + } tmp_array[20] = { + {"946039AC252CE6B23EA61D7BDA0513", "F8BEF7B2A66D0AFD25EEE5F00ED529", "E254169E1695F0FED5811EFECABE82", "D4B8DF1ACEDBC1238256803ECD5ED3"}, + {"EEDD17AABBF5C3C17FADE95E5E0F52", "FB0CE109B8434EDEEAEE39B180EA05", "83FA6FDAF01601187C02F8F9C9D531", "640DFAB8F9BA7C7045D8539E7DA167"}, + {"E1B7FF24B60CC3D6FAE0DF379E9C52", "77D1E3163B43C4A5F040DBB1D92C45", "C1C6BCCABE7779737DE6D5A0685714", "1E438B961131F3310502F23165D04A"}, + {"3BBCF51B5C023A4725E8C059D02761", "AC8E34AF71A315943A9AD2B6F3FD57", "5E07C58DE785277EF860CE77DA9D47", "4748B9B2DBAAAF9203D4311C994861"}, + {"8471505E1C6DC59719709438B78910", "C90CB967EF2ED10DAC592F321FD094", "8728CA6C946BE4C2F0B2D469CD8E5A", "04B19084EBE1CF71EDFE842AE184A8"}, + {"C8CAACDDB857D74E87ED947CE0D520", "B598BD0B4CB89FA1A78D9AABBB3142", "3C1489FBFFEE75675998EC8367273C", "230E44C7C341924368EBDB4B44725C"}, + {"8A529F853EE0EF4AD72E7C53ADEEF5", "D8757DF26B133B5DFE8B65491F1915", "91269FC8BD5376D3EC6413B837D497", "0B94F8663C6F65A9E509A745ACFF9F"}, + {"D45220BF290FC15F357DC88585FF53", "5F3B076B55BDA581204AADDB6E0469", "B9E7CE59CD52A91CF28A623F3DCDAB", "41937C9FCA6796391A9F3C688D14AB"}, + {"B4434CA8957DB9F492B832A214EF33", "24F4B1B1A25FC615FC40AF4E5C5D03", "FD098128C3B9D8185D7B92E0136C4E", "C196867A9771A200A7ED11025FA15D"}, + {"AE88934074A1D3B716D2EBC3FF74EF", "49CFE44A710E7D35AB3B0E71ED24DF", "7C0F7B56174097BD04C4AC23008375", "271F0E78BA2B2E961FCA04EC3AF721"}, + {"69D71BBE4065FEBF636621A9B398CB", "8F596874A63DB197E13BB8F555E569", "AD480269C59532A1B1D3A48A3EBFC9", "656BD1F3AF1DA4C55520A5022224D1"}, + {"3A77B2392D4B0120D2A6250101BEAA", "D3C522A5AAFDD2F79592A9C537CA7F", "83E0B72265E355898999C714805299", "4A826EF68977973F68090CF9C68856"}, + {"91E133017979FB86622DD953206DC7", "A64DEE9923D431F26563F2DE78B47D", "C2D38A16E83BEA9AA7AECC5C0572DB", "8D76C9F34C0DFCEF5433C0218FE1CE"}, + {"4FF8E538D25C3CD9C9CA4200D19B69", "D78D46FF5B12303785553AB9DEDCB3", "7FBC84F3B7B5F807776BE47B104167", "53B0EE1DB6B4D704765F664986732E"}, + {"129A01B2A4AA9A70E375FCA58C4C74", "23ABA7C3596A5EA96EE67FC3EBA3FC", "5FDD92D40D269CEAE833B385E1D18B", "04BA68A7667F166590E211F5457F0A"}, + {"16A6511BE51692635F3FA980DF155D", "D21D6BFE9281A37539D038727C3577", "6B70A440DCFF5666A97F06428944B5", "5C3F3482063C6A1D0EC2FDB00F53E7"}, + {"D349D30A8F33D5A62186C2998F56AF", "6D206CAC47F35A9918C5DE439D1A49", "9B06949ADF82822974336E48B7175D", "05462A81745552FFDA8C84C291C4CD"}, + {"AFCCC6F3D6BD83529100936DBBADBD", "671F2D69BC1A3DB2B5886B5ABF18D4", "201CE68B11CCD8EE12FBD2FA21686D", "1BD1340C0F7AA88652EB8C79C013A5"}, + {"13433B00C80F35A6171449ED43BA6C", "ECCED64E95AB40E08EBC0C40902DDA", "44ABEA5DFDAB6976615D434D7A740F", "049924CCD71A95EF1CA4DD66B1F151"}, + {"9B6CE45B82C93028AFF23E138622F8", "E376A96E5E0A9D96E8E24D43AB8CD3", "C8C48EF95F50CC70792B7645C150D8", "82F9DE3216076D3989457D8551B658"} + }; + + for (i = 0; i < 20; ++i) { + mp_read_radix(a, tmp_array[i].str1, 16); + mp_read_radix(b, tmp_array[i].str2, 16); + mp_read_radix(c, tmp_array[i].str3, 16); + mp_read_radix(d, tmp_array[i].res, 16); + mp_mulmod(a, b, c, a); + if (mp_cmp(a, d) != LTC_MP_EQ) { + err = CRYPT_ERROR; + break; + } + } + + mp_clear_multi(a, b, c, d, NULL); + return err; +} + +static int ltc_test_sqrmod(void) { + void *a, *b, *c; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, &b, &c, NULL)) != CRYPT_OK) { + return err; + } + + static struct { + const char *str1; + const char *str2; + const char *res; + } tmp_array[20] = { + {"5532CFBC0320EA53C345353A1EDE29", "3D9CDF2D3622716EF6BA73F8FF27C1", "291A850FEB581243F5D3BA3900A119"}, + {"7DC29F767734EF15E00067D879DBC2", "4A698AC26BD128913FE9C6C4179BCF", "48817620F4BAFC6025F14CFFE358ED"}, + {"4B7BF850D3E0AE720BC1C59EF29B49", "B34A6976978EA7DE753705C9DBC1EC", "11DEE38F5CFC0AC677E6178E17CABD"}, + {"0E8C164B36087852D0B3CC75BC538B", "AD01C1992E3E850AE310D62024211A", "11DF3A0359B62C8CAE61C735B591D1"}, + {"4D18285877BA3C04404E681A8F2AC7", "364339D2DB8421BE2DE47147B5B5B7", "1067FABCCBC6A8C9D666F83627C46A"}, + {"49B5D8E38DF8677EA8F9AB22D6FE24", "13E9794E15CD6227D358E03ED9FAFB", "0D2965FCB81DC95B2F831B6C337DFF"}, + {"45179D76CA7A9DB5166217EA8F2488", "4213ED48DEB0C159941B1783667245", "1A6197368A2BDD937B273DEE97A2E9"}, + {"870E665CC5ECF5C541381DB8C802BB", "66024D457FE40CD9E143A4515309F5", "45FD0428195F668F1DF33FCD1C894E"}, + {"FC280BC1A93CF9134B99821544C1BA", "04F1BA5C7D9DDF048E24F915B1EE15", "01BF9ED87AC161105EB74E5188BCC1"}, + {"C338130C2F8F676C8E26424D554299", "1D026135FC11D0E82BEC3928F473DA", "0F8E9CC66C06FB2DFF0ABD01F38F2B"}, + {"2EA5631FEC465AB04A925606BA7A53", "2A7CE8B95CBAC35AEAFFA5568248B5", "29BB61D34988A990A7F592981DEED5"}, + {"6353D50C37CF6570B6852000F153B0", "C930467A2160A057CB4D1712A5D7BF", "8F566DE34979A8DDD301D611A0E58E"}, + {"B795FBB6A60B3401F5812E23A80A25", "AAF33083E55E798403DF5866CF091E", "2F3F4C4832FF2A5D851DDBC337E3E5"}, + {"7B636AAE6615F0DD69B5BA363D1D1E", "46DDC0F6583C55395F8070E4DCB8D8", "0AF5CED3D58F6AE3BB29F621B9A8B4"}, + {"B8B217DD2A9B75081BA6C0B4714D33", "5F6533D6994BF6F021B5C735E62DAC", "159B90588F6F2D4DD8DC963166DA85"}, + {"B0C671CDBDCBCC3C4E85E4698E3C79", "8B1815606BE2D5344C9A5DBC55B6C6", "785808F197D23511AE67914CBDCD6F"}, + {"84C7BF642D9838C61C2C1F7121BE93", "F6CF617F95D7FBB51D3FDA022FD265", "B2F22ECB48CE37C1D5C52983709EDF"}, + {"CEE5ACB1876CAAF1C2B4049AF12800", "2CFB1AD02BC98AC310DF9FE88F7C90", "0E85F1E5EA47DF1DBA7E63D9EF3240"}, + {"6412AE04EEB6DFB5BCFDB8BF6E3BF3", "4ABBE3876415E883BF72F873C4EF49", "151594DF35400D47D9653A368B27CF"}, + {"03488696E1084D231173B1CB98B35A", "7DFCF0FBF5941E476589D37361F2E6", "0827C0F811D0A323007B45306F8848"} + }; + + for (i = 0; i < 20; ++i) { + mp_read_radix(a, tmp_array[i].str1, 16); + mp_read_radix(b, tmp_array[i].str2, 16); + mp_read_radix(c, tmp_array[i].res, 16); + mp_sqrmod(a, b, a); + if (mp_cmp(a, c) != LTC_MP_EQ) { + err = CRYPT_ERROR; + break; + } + } + + mp_clear_multi(a, b, c, NULL); + return err; +} + +static int ltc_test_invmod(void) { + void *a, *b, *c; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, &b, &c, NULL)) != CRYPT_OK) { + return err; + } + + // will test values that are invertible ! + static struct { + const char *str1; + const char *str2; + const char *res; + } tmp_array[20] = { + {"ACA47FF7B90428122D04A806F0C362", "8C1F5EABD66622D198ADAE2D46D53D", "493C6788F4DEBAF2A672E2818B8209"}, + {"9B837F3F57C0D06B6672F6F38DE92D", "B19B9C4CE8DDA7408D1A1DC8104B97", "86360789D7714A0E33DCF6AAB1819C"}, + {"077514FB4FF055F52C89D8EDE0FAC8", "99C0C3AF67C57882B4AB8B1E4F46A7", "8848D3241ACA2CC1470BCF00425E73"}, + {"DAF413A4A43CE5F00A917F5D2922A2", "F60FD31EE99D8493F8653EE163E521", "16872AF77E4E6055DC81C2B632BA78"}, + {"8E527FFA1DAE86D982499FDEB0FAB1", "FA93B603243150282293100433FB8F", "79558C76ED0A78C030780A13151081"}, + {"673535255FBECCA0DE03FE91716154", "1C8A0CAB7CB93F772FBD20D54CEBCD", "1A1347ED9E552072687665FBC8EB38"}, + {"4DA878A37F383C2340C33CF56B98D0", "23D4AB0F97BC607C57E15D3F4B9BD9", "1938E4B5BC4D070FA34F7D166DB121"}, + {"9176AA936C7792C8C82BB0CAB6D98E", "ED352A694240A6F0C7F218C6148F1B", "97765BB1CC6AC815F9D8486A6849F5"}, + {"3BB05C35303BBA518B0F432F173AE3", "DA2D3B6C1ADBA3D1183048A685020F", "83A24AD3BAB0AB3BE8B1BA68E944B5"}, + {"DD49482E74135DF4D093606054C801", "601122A19C853CE436DCE376C63B5F", "31F71306CEBE4BC6854C40A26A9773"}, + {"788BDBEE8E041C5F0A87E37D954357", "56CAD67DBBFDDBB6F8033AAC46C8FF", "20E0DE5C06AB37ED9D44599BC80DD8"}, + {"25F1D64019121F9D3FDC1882E7E210", "CBEEF1B3AA827D514E25927EF4AD65", "5C87C029F51BFE65549503170BDD72"}, + {"96A843777936EBEE4593F40E8ABEEF", "534D93681B08EA0EF1ED404C983EFF", "28AFC16042C761C505708D899CF9F2"}, + {"ECFC202D1E1A5D82EAF83F72CE0A2B", "9685ABBC9B5FE3849CE29E6C6A98A9", "0D396DF965F7DFF78B2D4A2A2370E8"}, + {"8BB41426A845235758C582DF740A12", "D26A1F480A50C22FA57E031C2AAF45", "37C45A260BCFC57DFBC4FA3323DF3A"}, + {"C5D860BEA3B9E1354F17D24FFE56A6", "EA9106469622B6F1DB31A4160098B3", "9678B7B0BB00F4E6A4F98D56DC2D36"}, + {"95150D8B4288B45F29C31A8A816F79", "0A0EB58CEF892962AE571E62EF247F", "5E1C1CB4F0FCFFDC2E1B9B83032D"}, + {"A6EA9323744DD36F8ADCD347288A8C", "3E3AB30D230A1371EEEB256E0F53F7", "12600AC1CA658AAD247C67C7C33D0D"}, + {"B55479E34DDB425FCC4FE0BF0688CF", "BC7BAE226019E0A025FC427C0D2775", "305D8FCF357EBE918732441209C16C"}, + {"277811283AB608B5EF4270CDB86B6A", "1548F5562FF905DCBD615971C12587", "06EB29633C3E2B37B386688486D62A"} + }; + + for (i = 0; i < 20; ++i) { + mp_read_radix(a, tmp_array[i].str1, 16); + mp_read_radix(b, tmp_array[i].str2, 16); + mp_read_radix(c, tmp_array[i].res, 16); + + if (mp_invmod(a, b, a) != CRYPT_OK) { + err = CRYPT_ERROR; + goto end; + } + if (mp_cmp(a, c) != LTC_MP_EQ) { + err = CRYPT_ERROR; + goto end; + } + } + + // will test value that are NOT invertible ! We will check that + // the function correctly returns != CRYPT_OK + static struct { + const char *str1; + const char *str2; + } tmp_array2[20] = { + {"7FF79FF91F5B6847213AD34294447D", "A8C80E7E9969548AA71CE8CCA965D2"}, + {"0713DC8D76F7CF460055724FCAEEBB", "63DC32AFB93BF6F7D5ED74A94F23"}, + {"5EE7AE62E6D2B60309586EF4BF1328", "4E8E13954FFC8799EEDA849074212D"}, + {"161382A7FE8E8E62844F2DE6687E3B", "2B65B4AE3A2515A89226F64C55DD61"}, + {"9A4FFBD1568C82DBDDBF8945D12FAE", "500C43E76E25BE64E56F0F5D876F69"}, + {"26DBBE1A2C855DFBC1C294A5107217", "285DBF89D7621233E24612B133D179"}, + {"2C20C8DFB30B0D147898DB11AFD51F", "221C6FE2D35E154F8193684362BB51"}, + {"63F9FF4D485192908ABE76005F3B13", "4330FA36462058EAF65E9E42FC5C29"}, + {"1F38BD5323ECB5E145C7B8D39400CC", "2A673DFD8008B35616CF385B34BDAE"}, + {"AA83BBCACD54C511593FBA0928E049", "4D6A365796AC4D98DB578F331BBF3A"}, + {"1A5B6FE363FFA100D34293B3E894", "6A08181171B462732E8C937F29B2"}, + {"A9CE6E30F5FAF036C4EFFD41A53FF3", "B42E0D73BF6E993480AAB7A01B2274"}, + {"0756497DB54DE2EBD9E25C11C8AF38", "46E4610FEAAC6EF8EB5843B147DFB8"}, + {"4F6E24F192439D7BA41C85BAFE6D40", "07329F31D6E6B3C27E75C1F33FE1A0"}, + {"4B437F6B1809B71EC8288B3E0501E6", "4A0E56AC39F52A86B68604C8A4A7CF"}, + {"317F3F5CBFF36092B3EE3603E9C831", "6325FFA459A4AA6CD5BDD6A201376E"}, + {"A43A32681E36FD0B95EA48DBBB7567", "327B513E1342D90DA01E7FAEB0D9AF"}, + {"1711CE0859A227D14871F36317A655", "237A3CA84256E53DCAF1DB998A51CF"}, + {"34A1BBB30400345DC7AEEC57C72E54", "09FC8E322D68F9F987BB4A199362D5"}, + {"0ABD39AEB74838140AD9A22A4279C7", "2204D2BE390F923F3329370602B50E"} + }; + + for (i = 0; i < 20; ++i) { + mp_read_radix(a, tmp_array2[i].str1, 16); + mp_read_radix(b, tmp_array2[i].str2, 16); + // the function invmod MUST return != CRYPT_OK + if (mp_invmod(a, b, a) == CRYPT_OK) { + err = CRYPT_ERROR; + goto end; + } + } + end: + mp_clear_multi(a, b, c, NULL); + return err; +} + +static int ltc_test_exptmod(void) { + void *a, *b, *c, *d; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, &b, &c, &d, NULL)) != CRYPT_OK) { + return err; + } + + static struct { + const char *str1; + const char *str2; + const char *str3; + const char *res; + } tmp_array[20] = { + {"A4BAB4CFE0F15C52B4CB6FDCF2FC01", "4E3E246BAD88F1A262452026EC56EB", "DABC8363B0819E86DA02DA91EB00AD", "98AEE445F6B7BABFB8400797665FBF"}, + {"35E719B21FFBD2E5C136F5729BE667", "14F82D0C889D285A5A194318CB3162", "0E038ED782D76A92347FA8AF850313", "060D9CB89407E5B9B8B7E55DB5DD75"}, + {"CAC958BE320C0DEBAB55B093A1867E", "8BC1CB1E43C8A8AB594B495345C988", "AC2C1C32BF39BF8E8B8253EA453523", "0759A5440F798AE4A18CFC1BE7FE86"}, + {"96B5DE43B52F43A3851580E467D941", "F39F65576E544409C8AE540C935015", "583F716BB44BEF32CF36DED0EC85DB", "42ADFBE1F980C4A116F7B812589ACA"}, + {"1C8882DCF340123A61AE3D6B06B028", "1C1417979EDCDE78ECCB7BD367D411", "821FDD6833C7CF4085234FAAB3E31D", "1A6D52682FB32035F999DFC8DA5D56"}, + {"2C7F536A21AE7023756FA40243E8B8", "EC1163D1B3E48DB1BE0E5CE33AEC3A", "0F5F228411E42CBE6A156C4DD65F83", "030693311660176629C0B03FDF23BC"}, + {"E25B642C8DF8B369D7CD603509DAFE", "0ED017666D8E9DF07C4AB613C4B40A", "AFC18FD2A8C952C20A2E029EDB95DF", "6DF660CEFEF2B1929F40B4ABBE9D2C"}, + {"66F4E4177A7F69FD848E86A7C33A71", "9B4B79613E93241592BA64CE2586A7", "85F2BA3B161442B528B15A1449E037", "07CF42B332CA023984E7E49A8BA1BF"}, + {"A8145A149C156822474E39A98B5513", "701EF637F67CAD70634F5141956521", "FE2E0B1A0FE1B2E2606AD32D3EEBDD", "9ABD2609B27E55E13DC0C86C699292"}, + {"5B65A816AC21F84D14B0262FAE16EB", "39A0273AE867374F6B008AA6621033", "137EE3F0774BA7E82ACAE2EA66F1D1", "097DB633871AED8A7364AE983D30B0"}, + {"FF66DA7FAFF640378B718AB9C47FE7", "4F4E718AE34AAC99EFBD769AA9BD41", "6D43F29085C78A1F70111D25F7C1EB", "5285227DBDDDBF6E3967347509A6DA"}, + {"5FB717F6EBDFA8C36ADDF30DEEC361", "814FA371CAC2F23CA08B0B65FF8038", "26D346E9A9452C44F9945954F25ACD", "06E7616CBAC8727153BB8A303514F7"}, + {"67B7B3770292B83F9BE6B641FD52DF", "51E40A7D43D7A295359FC409B5EE86", "0B9C2C5071184D5C8FDF64D88331DB", "0A9FFC90CD0AA23CA41989146CD349"}, + {"7077ED1834A591A6D4D862DCF46DB3", "29BCA4C9AF393620AB61C90C26A2E6", "AE66CAB0CA4D4E3944DE45A969E993", "35127FC8E26099F8D88AA1432FA67F"}, + {"90E4D9A8D5C7FAFFB47860CDED6C29", "E4DB5F0DAD6C2E3E43ED36C368E70E", "FA7CA09EEF3A8D7AE1A62814CAE34D", "23484425E1CB128D40DD4F08515F8C"}, + {"F5F1FCA6DDC99B62C27ACB9BC73FDE", "65C8A9A9DB5DB87325ABA0325B1B46", "714D8D87C8DAA1053CA88849C925A3", "0426F970ECEA0C2A8B09CDC44B8A67"}, + {"B93251B6B3CCAC22EFB0390A8CA327", "57D3AF6BD3FACC20C06CFDE292A217", "A30973D2D17B040594ABD5F7C333B5", "64418E32CCD1602FD5998A7B0B0036"}, + {"E0B189C3608F153E901B2B1D417F2F", "99FC8A18CC12ACFFFFF4D67E5FAA75", "94952082DCB712D930AEF801DC1F73", "4EB73F6C2BC5A2B7295AF48F9ACD4E"}, + {"F0783E2B6EB5AC4585CBA6BC05C451", "6475288C76373CF734B21932FDB3C6", "E1E470ADFB1C3DF4D9C9339BA1CA09", "DABD657BADD65D3387EABB0AF81E03"}, + {"68F51480C777D52876880F02353903", "B6D65D5831FE3A683F4CC8589398C2", "31D1886FFA886AB9BF58F33E0CD085", "0C896B4D0D398F124BC0F7E964E289"} + }; + + for (i = 0; i < 20; ++i) { + mp_read_radix(a, tmp_array[i].str1, 16); + mp_read_radix(b, tmp_array[i].str2, 16); + mp_read_radix(c, tmp_array[i].str3, 16); + mp_exptmod(a, b, c, a); + mp_read_radix(d, tmp_array[i].res, 16); + if (mp_cmp(a, d) != LTC_MP_EQ) { + err = CRYPT_ERROR; + break; + } + } + + mp_clear_multi(a, b, c, d, NULL); + return err; +} + +static int ltc_test_isodd(void) { + void *a; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, NULL)) != CRYPT_OK) { + return err; + } + + static struct { + const char *str1; + int is_odd; + } tmp_array[20] = { + {"B90C9F9A947FAD908154EF87378930", 0}, + {"03712E58C6B5469D3C96C512D0C546", 0}, + {"7C2E3CE01381E7F420E330922EE290", 0}, + {"6322E1CD41BCE762627674376BF185", 1}, + {"56D15771EF973502595EEB411ED37D", 1}, + {"23C0BFEC124BF994C83CDEF7C9ACD8", 0}, + {"A98C226A9C72F2E3CC10E6D90580A8", 0}, + {"CDDAB6FCB974B209A8E27F11F800C8", 0}, + {"40ADB1A9DE33A1C16791938D494FDC", 0}, + {"41EC98B63EB149CF8A8E72795C8580", 0}, + {"0DF0D72C2C207CF8ACDF7D5BD12DEB", 1}, + {"02B36353A2A846C226F57376599E90", 0}, + {"3E1F14E821C4531AB039DD57D8C5E2", 0}, + {"D10974B495D4A56D3FB6EDC0332935", 1}, + {"69A6C36374BB6AF91654464AE75453", 1}, + {"B8A56F350324D1B26247FCC5AB045C", 0}, + {"DD8E60D8C8811493369D4B5BF0C0BF", 1}, + {"90C0430CABE7A924D3FC8B042E348C", 0}, + {"B51222B32474F63258FC0707C26023", 1}, + {"C4BCF4995A2A5278B0F7199D27EC4A", 0} + }; + + for (i = 0; i < 20; ++i) { + mp_read_radix(a, tmp_array[i].str1, 16); + if (mp_isodd(a) != tmp_array[i].is_odd) { + err = CRYPT_ERROR; + break; + } + } + + mp_clear_multi(a, NULL); + return err; +} + + +static int ltc_test_montgomery_setup(void) { + void *a, *b, *c; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, &b, &c, NULL)) != CRYPT_OK) { + return err; + } + + static struct { + const char *str1; + const char *r; + const char* r2; + mpa_word_t n_inv; + } tmp_array[20] = { + {"2814CD485F1227FE4AF246F7754D31", "0324EAC8CF0A92E756A4C18DD4000D", "16912827593513EC5276DFFD0A3130", 1453265967u}, + {"7F4D82B18B3C70283002A3C27ABD29", "665F978670A6CF4F9AB333859033AE", "086AA154E7E99B6C0B0890DC99F6E7", 3235827943u}, + {"3D447BC8073082E66CD5F21D3C654F", "29071DB9FA6D63CB869BFBEACCF51D", "1B4F299449B1C31FC880EC2730228F", 3471076945u}, + {"BF0326D4422166483D8396825C878F", "12C6F99B653FF53594B15756065F67", "4B016C1494DAF269CBDB33949D4F3E", 1905870993u}, + {"89DE6875DC74F41EEF2C1AA2F9121D", "30542D4FF2FF0A9A392A939BDB6431", "4AF53AA44E7639FA209AE886859F44", 1861730251u}, + {"87CC19B987EE8387BA35F4736D3FF3", "51B790AE10EC5A736669BEAC4D987A", "1E3EE8DF35781239DCFC6C76BEA70A", 2700578501u}, + {"BB37211E5F4791635119F598E31401", "0AA0B879BC273A371E8238F98AA6A2", "A6383C6A42007326BB72AE02A6125B", 1599280127u}, + {"FA88AC39727F354D39323228D5F8D7", "92A8696E444EA844AFD2DC5DD94CCD", "8D1F7FFEE8FB4C8142CD51FEDA7C4E", 879068441u}, + {"349FF0A2456ACC1B3F7FFD66F7BA75", "122ABAD4679D5F7C2E8CA23D3A34FF", "1C8097289F864C19907A12B5242F8E", 2985769507u}, + {"96058FA327E584E6E6DE7A16415BF9", "7E875E200D19A6BECD181218AF5BEC", "31FA069CF92C767C92858BF62FF2BA", 860326327u}, + {"FE82D976F19E89C7A900D6C979F657", "7EA3AF976FD7AE8F56285FBC8FB2A9", "E6FC4B83CB17D70280AB4A0E54341F", 3689589401u}, + {"0E64F7C261797D7BB3DC8E6E04E3C9", "0CAA87AAC7C0C069D63B6BB90DB1F8", "06B751E0D5FF372198854E8C3B9B19", 1709398407u}, + {"6779CC0E4AF2025EF58A83A4460C9D", "23D670A8AF982332DC807ECECACFCB", "65DFA3171B0D31BAF467651E106804", 1570186827u}, + {"7D03ACD33208158F379363DE14FE67", "1C7A3FB59773DEDA3E4F956D07452C", "6410B6F7C7864924DC7E0FD98A2505", 1570161321u}, + {"2836C57F3BA7F7023A95031A63CF7B", "1B794561643136D139CB4112E0BE51", "09BC2A0D477443CBF1DD513091AB0A", 3068151885u}, + {"A430477B91151D62FB621E905E9CFB", "18C09668E01732BA32125CFC8954CB", "0F55B8058EF90D4EE55043BFE9692B", 3307008461u}, + {"D8858250E2A90BB671750F5D2CA2AD", "928044949C942EC627E7E0155817EA", "CD4FAA4E3D7BE2E520D4800852E57D", 1080356571u}, + {"8B6B15BD7C4D2826639107B2D21EF7", "0966161DCA58498533BBDDB23B2686", "8086FA9537812147D19C0E7E84321D", 3725327673u}, + {"17178DF37618F51DAA98797F65AF3D", "E05700C752A91EC9AD15AEBB51C2", "0E8F66B4F090AF5CF05050707677DC", 1110106091u}, + {"8942D9FB7C331ED9A4A4ABF50FC4F9", "3E6FD66994BF8478392B98619DFC0B", "875BFAD4E2908559B30B8320CD0229", 2936160951u} + }; + + for (i = 0; i < 20; ++i) { + void *mont; + mp_read_radix(a, tmp_array[i].str1, 16); + mp_montgomery_setup(a, &mont); + mp_read_radix(b, tmp_array[i].r, 16); + mp_read_radix(c, tmp_array[i].r2, 16); + if (mp_cmp(b, ((mpa_fmm_context)mont)->r_ptr) != LTC_MP_EQ || + mp_cmp(c, ((mpa_fmm_context)mont)->r2_ptr) != LTC_MP_EQ || + ((mpa_fmm_context)mont)->n_inv != tmp_array[i].n_inv) { + mp_montgomery_free(mont); + err = CRYPT_ERROR; + break; + } + mp_montgomery_free(mont); + } + + mp_clear_multi(a, b, c, NULL); + return err; +} + +static int ltc_test_montgomery_normalization(void) { + void *a, *b; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, &b, NULL)) != CRYPT_OK) { + return err; + } + + static struct { + const char *str1; + const char *r; + } tmp_array[20] = { + {"61FEBFB2314923F624A78E759CA8BD", "4B43CB07652629B85AC8451B37B2D4"}, + {"CE9E61C08BF0E73E33409B04BFE037", "25E0F492B6B1A7FA89000B1E675BE5"}, + {"BC4B562DEB94A2880C879355029CC7", "0996D993C1F30F0EF7B3B87072E17C"}, + {"4DE131E629F57811EEA5FAD8291CC7", "273312E028988D1700BAEFE0F07641"}, + {"F021B7A735F93AC73B4CE395ED49C3", "DC2CDE56A7318C50FE4E30B3E1A0D0"}, + {"4A033428E886ECC4EDC05403E3CE7B", "22ECAE94258F7B36161D8E8D7730C9"}, + {"51FDA55EF9021D470EE80ECA851B11", "1958DC94D2669F3879B9D5EA9085F1"}, + {"086B575AE67C1C67185B3316252149", "27DC0FD24061436AF6A6A703EC58"}, + {"C78A54D0058EB54C086714B786547B", "56C35578E127B6953BED74DBE3C268"}, + {"BA15AA51BDD5119E6883F9A028BC15", "2235CF9AFB07C6304A88C3C7FD6320"}, + {"22A1B070849AE14C13005D6D8DF8F7", "0D04006BF756E9C3914D8252BBFE84"}, + {"B479FD78000825181FF4CB04122353", "170596D7F47366CAAFE4213A47E94F"}, + {"FC1984D172E9709FFED6B1586B2F83", "F22EA018BDD30E212CCA938B8EEE77"}, + {"7CFFC0A55A1D1385C661147124E289", "2481AD8B8C7C0A2DF14A2868804F94"}, + {"D3B5307A4FB5EF0D587824798DBAE9", "764C7C5DC96674E436FBF947ED64C3"}, + {"BCEC3D4E0BE0112A9998B2222B89CB", "A8B52483F328CC6C679F3DD127C3A2"}, + {"0EC3B8E8263DDA1B1E6F58DDD5C95B", "0AF877790BBCEDDE61B16A47CF506E"}, + {"C543579D275C3F6CA41ED550169FCB", "2CAA6030F45DBF1B28035C22A8C4BC"}, + {"B648CEA11E5D23197DA2EC67615CE1", "5FE63C0E6B63C740D0867B0676C079"}, + {"B3E4F977C8E846282F914C101AED13", "366D49AE55BC3EDC5D67D919B6E8FC"}, + }; + + for (i = 0; i < 20; ++i) { + mp_read_radix(a, tmp_array[i].str1, 16); + mp_montgomery_normalization(b, a); + mp_read_radix(a, tmp_array[i].r, 16); + + if (mp_cmp(b, a) != LTC_MP_EQ) { + err = CRYPT_ERROR; + break; + } + } + + mp_clear_multi(a, b, NULL); + return err; +} + +static int ltc_test_montgomery_reduce(void) { + void *a, *b, *c; + int i; + int err = CRYPT_OK; + + if ((err = mp_init_multi(&a, &b, &c, NULL)) != CRYPT_OK) { + return err; + } + + static struct { + const char *p; + const char *n; + const char *n_mod_p; + } tmp_array[20] = { + {"DDC418ADCAB00456FC187EA0434E0F", "7149BF2EF402AC0F67C6008C5D72AD4BDA375E53AFD22F7FB5B13C037FB0", "BFC3DD062CD27DE20471D724C37A5A"}, + {"09171A1A577037E27A7BA669762809", "25A09EEBF24301AABFD74E6196564371428A30D72103EE399C4033A992", "FC772DA2AD6C11AB43B37F8B641E"}, + {"C96A521CEB2B9433B07E365F431757", "6B7DDC41E753912CD39D1055598C94438495F0AD2127D3B09BCCB9E42960", "623E6EC8B8A9EA9D7AB5D18A93C891"}, + {"7D2E7915089BEE7DABA4F56A0769E3", "3D05411A4512A2D9037077010154ADEF5AB48A74BB9D99DC28717ECC4490", "3975211A24ED994A99D8D861CA4277"}, + {"06F06B83AEA77716ECEE9F0143380F", "0ED78D002FEA886AC234E3A3AD41BC9745047DED61D8CF40F803A9E4D9", "0687184AC0861B76E3ACBE1EAA24A3"}, + {"48C45945075280B2452C8C8F131FA9", "0FA11CA339A9254370A013F73581D9985151B746EB23977745BE4F722CA6", "2E7741F5DD60A0334450B5A116DF7B"}, + {"40ED19EB4828515F73A1BDE88E1373", "05F636AE2AC5AF3C53D2F5B0143BAB284D8D593E8B4AE17CDC7A6E23FF2B", "07898E0915EA776D32BD0CA1ADE0B6"}, + {"79919FC4862E17B8781B206E347227", "39287B3F8D4AC38E302ADB600B4D6592990776D76D06E8B7CBAEA93EAE20", "38305C0F26ED021D1AC3366BF6B444"}, + {"90099DC51C74F74F69E9F757EEE875", "2BB9543F9C634BC8027F91E557C1F62F86101E13784A1E94A1B1E0DFC75C", "7DF0A23F494C64DD8CFAD2A99CD1A8"}, + {"DBC6ED9586088E1DBFE8D1616E5297", "AFF3DA273D793F9A1B78773F952ECD462B41F374688DDFF439B27C1E5F04", "271054D840E344F723FED9BE0CBF03"}, + {"3C2622793D457098CE762D62B597E3", "0D2361BF27A47C1CE1640CC563411A3CE62A57682EAA53150C538C56B477", "1DF5072CFF95BF4966A893E5964070"}, + {"58F98523DF9E583E80CA8B76367A1D", "1CF5DE923A53E95EE2351F70A6098BDA7A1D438AC9914A62AA1205257B17", "303CBDECD6F9E515AF77D52CE0F423"}, + {"DB8FA21A02CD5C4619F15ECDA6313F", "222091493EDF5DD96CFEC9927666B895F4C04A7A98BD7EAE799540C8C388", "6C1F5DE1756F18280266D69C73D4EB"}, + {"5D7B0BF6FDE092B12F98DB6E7D60C5", "115CDD5A83C730029333009AA3D3B42ABB4177BC03B2D7B64266E8235221", "1C70B47027B93459E5DA83DD84A30F"}, + {"D3795DF6CF776199AAD4094B2E7587", "90A986C673E70E548DDBE169444331F3B86FC572E7FA90FEBD26E5723D6B", "C181627DD32F4EC02E9A7A2CA686C5"}, + {"6AD652BBF598782D7CDCDADFEFE36F", "09CCC26707D5F77D44E422980C50E2E91E7FE35201C0EEAA44FB750F6D98", "60DA8339731E6AA0C7A7A9BE0CDBAC"}, + {"14E0E490E8947F78E389779EE9F2A3", "019E570BD730ECE7FBC93E272DB46E7C9A6027476724EDB9E4C8F1A45B8E", "07AE2611396A3048798FEDEC173E3B"}, + {"79D539ABF638E2B74C8D06C6E74BDD", "2E8CFAA9C96F3D00CBE096E350D13100336D52116F080C8D1ED5CBCE3EBE", "33899FCA51FFFDC4A6E8CEDEB29EF6"}, + {"5B7486F361C66753D15A5BB3C2431D", "1F9715DBBD045112E351C6F5C95A9ACC975D8FA6AAA61A9EE9E07A8500BA", "5471BD9791FF2E7C2FCB7AD30846E2"}, + {"CE93293F937127D09D1C1D84C20B4D", "800406CDA0343081FD4C3E48F2519BE933008C4140AECD305B09450B2249", "A3A6F8C2DA772042A65A80D5915EC3"} + }; + + for (i = 0; i < 20; ++i) { + void *mont; + mp_read_radix(a, tmp_array[i].p, 16); + mp_montgomery_setup(a, &mont); + mp_read_radix(b, tmp_array[i].n, 16); + mp_read_radix(c, tmp_array[i].n_mod_p, 16); + mp_montgomery_reduce(b, a, mont); + if (mp_cmp(b, c) != LTC_MP_EQ ) { + mp_montgomery_free(mont); + err = CRYPT_ERROR; + break; + } + mp_montgomery_free(mont); + } + + mp_clear_multi(a, b, c, NULL); + return err; +} + +static int ltc_test_rsa(void) { + + unsigned char in[1024], out[1024], tmp[1024]; + rsa_key key; + int hash_idx, prng_idx, err, i, j; + unsigned long inlen, outlen, tmplen; + void *a, *b; + + hash_idx = find_hash("sha1"); + prng_idx = find_prng("yarrow"); + if (hash_idx == -1 || prng_idx == -1) { + fprintf(stderr, "rsa_test requires LTC_SHA1 and yarrow"); + return 1; + } + + if (mp_init_multi(&a, &b, NULL) != CRYPT_OK) { + return CRYPT_MEM; + } + + for (j = 0; j < 20; ++j) { + DO(rsa_make_key(&yarrow_prng, prng_idx, 1024/8, 65537, &key)); + for (inlen = 1; inlen <= 86; ++inlen) { + /* make a random key/msg */ + yarrow_read(in, inlen, &yarrow_prng); + // printf("\n\nin = "); + // for (i = 0; i < inlen; ++i) { + // printf("%02X", in[i]); + // } + outlen = sizeof(out); + if ((err = ltc_mp.rsa_me(in, inlen, out, &outlen, PK_PRIVATE, &key)) != CRYPT_OK) { + rsa_free(&key); + goto end; + } + // printf("\nout = "); + // for (i = 0; i < outlen; ++i) { + // printf("%02X", out[i]); + // } + + tmplen = sizeof(in); + if ((err = ltc_mp.rsa_me(out, outlen, tmp, &tmplen, PK_PUBLIC, &key)) != CRYPT_OK) { + rsa_free(&key); + goto end; + } + // printf("\ntmp = "); + // for (i = 0; i < tmplen; ++i) { + // printf("%02X", tmp[i]); + // } + mp_read_unsigned_bin(a, in, inlen); + mp_read_unsigned_bin(b, tmp, tmplen); + if (mp_cmp(a, b) != LTC_MP_EQ) { + rsa_free(&key); + err = CRYPT_ERROR; + goto end; + } + + } + rsa_free(&key); + } + + end: + mp_clear_multi(a, b, NULL); + return err; +} + +static int ltc_test_dsa(void) { + + void *r, *s; + unsigned char msg[16]; + dsa_key key; + int prng_idx, err, i, j, stat1; + unsigned long x; + + err = CRYPT_OK; + + prng_idx = find_prng("yarrow"); + if (prng_idx == -1) { + fprintf(stderr, "dsa_test requires yarrow"); + return CRYPT_ERROR_READPRNG; + } + + if (mp_init_multi(&s, &r, NULL) != CRYPT_OK) { + return CRYPT_MEM; + } + + for (i = 0; i < 10; ++i) { + /* make a random key */ + DO(dsa_make_key(&yarrow_prng, find_prng("yarrow"), 20, 128, &key)); + + /* verify it */ + DO(dsa_verify_key(&key, &stat1)); + if (stat1 == 0) { + fprintf(stderr, "dsa_verify_key "); + err = CRYPT_ERROR; + dsa_free(&key); + goto end; + } + + for(j = 0; j < 20; ++j) { + /* randomize the hash of the message */ + yarrow_read(msg, sizeof(msg), &yarrow_prng); + + /* sign the hash of the message */ + DO(dsa_sign_hash_raw(msg, sizeof(msg), r, s, &yarrow_prng, find_prng("yarrow"), &key)); + + DO(dsa_verify_hash_raw(r, s, msg, sizeof(msg), &stat1, &key)); + if (stat1 == 0) { + fprintf(stderr, "dsa_verify hash "); + err = CRYPT_ERROR; + dsa_free(&key); + goto end; + } + } + dsa_free(&key); + } + + end: + mp_clear_multi(r, s, NULL); + return err; + +} + +int unit_test(void) { + DO(ltc_test_neg()); + DO(ltc_test_add_neg()); + DO(ltc_test_copy()); + DO(ltc_test_set_int()); + DO(ltc_test_count_bits()); + DO(ltc_test_cnt_lsb()); + DO(ltc_test_2expt()); + DO(ltc_test_toradix()); + + DO(ltc_test_add()); + DO(ltc_test_add_d()); + + DO(ltc_test_sub()); + DO(ltc_test_sub_d()); + + DO(ltc_test_mul()); + DO(ltc_test_mul_d()); + + DO(ltc_test_sqr()); + DO(ltc_test_div()); + DO(ltc_test_div_2()); + DO(ltc_test_mod()); + DO(ltc_test_mod_d()); + + DO(ltc_test_gcd()); + DO(ltc_test_lcm()); + + DO(ltc_test_mulmod()); + DO(ltc_test_sqrmod()); + DO(ltc_test_invmod()); + + DO(ltc_test_exptmod()); + + DO(ltc_test_isodd()); + + DO(ltc_test_montgomery_setup()); + DO(ltc_test_montgomery_normalization()); + DO(ltc_test_montgomery_reduce()); + + DO(ltc_test_rsa()); + DO(ltc_test_dsa()); + return CRYPT_OK; +} diff --git a/core/lib/libtomcrypt/test/x86_prof.c b/core/lib/libtomcrypt/test/x86_prof.c new file mode 100644 index 00000000000..7ddf4f67219 --- /dev/null +++ b/core/lib/libtomcrypt/test/x86_prof.c @@ -0,0 +1,1436 @@ +#include + +prng_state yarrow_prng; + +struct list results[100]; +int no_results; +int sorter(const void *a, const void *b) +{ + const struct list *A, *B; + A = a; + B = b; + if (A->avg < B->avg) return -1; + if (A->avg > B->avg) return 1; + return 0; +} + +void tally_results(int type) +{ + int x; + + /* qsort the results */ + qsort(results, no_results, sizeof(struct list), &sorter); + + fprintf(stderr, "\n"); + if (type == 0) { + for (x = 0; x < no_results; x++) { + fprintf(stderr, "%-20s: Schedule at %6lu\n", cipher_descriptor[results[x].id].name, (unsigned long)results[x].spd1); + } + } else if (type == 1) { + for (x = 0; x < no_results; x++) { + printf + ("%-20s[%3d]: Encrypt at %5lu, Decrypt at %5lu\n", cipher_descriptor[results[x].id].name, cipher_descriptor[results[x].id].ID, results[x].spd1, results[x].spd2); + } + } else { + for (x = 0; x < no_results; x++) { + printf + ("%-20s: Process at %5lu\n", hash_descriptor[results[x].id].name, results[x].spd1 / 1000); + } + } +} + +/* RDTSC from Scott Duplichan */ +ulong64 rdtsc (void) + { + #if defined __GNUC__ && !defined(LTC_NO_ASM) + #ifdef INTEL_CC + ulong64 a; + asm ( " rdtsc ":"=A"(a)); + return a; + #elif defined(__i386__) || defined(__x86_64__) + ulong64 a; + asm __volatile__ ("rdtsc\nmovl %%eax,(%0)\nmovl %%edx,4(%0)\n"::"r"(&a):"%eax","%edx"); + return a; + #elif defined(LTC_PPC32) || defined(TFM_PPC32) + unsigned long a, b; + __asm__ __volatile__ ("mftbu %1 \nmftb %0\n":"=r"(a), "=r"(b)); + return (((ulong64)b) << 32ULL) | ((ulong64)a); + #elif defined(__ia64__) /* gcc-IA64 version */ + unsigned long result; + __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory"); + while (__builtin_expect ((int) result == -1, 0)) + __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory"); + return result; + #elif defined(__sparc__) + #if defined(__arch64__) + ulong64 a; + asm volatile("rd %%tick,%0" : "=r" (a)); + return a; + #else + register unsigned long x, y; + __asm__ __volatile__ ("rd %%tick, %0; clruw %0, %1; srlx %0, 32, %0" : "=r" (x), "=r" (y) : "0" (x), "1" (y)); + return ((unsigned long long) x << 32) | y; + #endif + #else + return XCLOCK(); + #endif + + /* Microsoft and Intel Windows compilers */ + #elif defined _M_IX86 && !defined(LTC_NO_ASM) + __asm rdtsc + #elif defined _M_AMD64 && !defined(LTC_NO_ASM) + return __rdtsc (); + #elif defined _M_IA64 && !defined(LTC_NO_ASM) + #if defined __INTEL_COMPILER + #include + #endif + return __getReg (3116); + #else + return XCLOCK(); + #endif + } + +static ulong64 timer, skew = 0; + +void t_start(void) +{ + timer = rdtsc(); +} + +ulong64 t_read(void) +{ + return rdtsc() - timer; +} + +void init_timer(void) +{ + ulong64 c1, c2, t1, t2, t3; + unsigned long y1; + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < TIMES*100; y1++) { + t_start(); + t1 = t_read(); + t3 = t_read(); + t2 = (t_read() - t1)>>1; + + c1 = (t1 > c1) ? t1 : c1; + c2 = (t2 > c2) ? t2 : c2; + } + skew = c2 - c1; + fprintf(stderr, "Clock Skew: %lu\n", (unsigned long)skew); +} + +void reg_algs(void) +{ + int err; +#ifdef LTC_RIJNDAEL + register_cipher (&aes_desc); +#endif +#ifdef LTC_BLOWFISH + register_cipher (&blowfish_desc); +#endif +#ifdef LTC_XTEA + register_cipher (&xtea_desc); +#endif +#ifdef LTC_RC5 + register_cipher (&rc5_desc); +#endif +#ifdef LTC_RC6 + register_cipher (&rc6_desc); +#endif +#ifdef LTC_SAFERP + register_cipher (&saferp_desc); +#endif +#ifdef LTC_TWOFISH + register_cipher (&twofish_desc); +#endif +#ifdef LTC_SAFER + register_cipher (&safer_k64_desc); + register_cipher (&safer_sk64_desc); + register_cipher (&safer_k128_desc); + register_cipher (&safer_sk128_desc); +#endif +#ifdef LTC_RC2 + register_cipher (&rc2_desc); +#endif +#ifdef LTC_DES + register_cipher (&des_desc); + register_cipher (&des3_desc); +#endif +#ifdef LTC_CAST5 + register_cipher (&cast5_desc); +#endif +#ifdef LTC_NOEKEON + register_cipher (&noekeon_desc); +#endif +#ifdef LTC_SKIPJACK + register_cipher (&skipjack_desc); +#endif +#ifdef LTC_KHAZAD + register_cipher (&khazad_desc); +#endif +#ifdef LTC_ANUBIS + register_cipher (&anubis_desc); +#endif +#ifdef LTC_KSEED + register_cipher (&kseed_desc); +#endif +#ifdef LTC_KASUMI + register_cipher (&kasumi_desc); +#endif + +#ifdef LTC_TIGER + register_hash (&tiger_desc); +#endif +#ifdef LTC_MD2 + register_hash (&md2_desc); +#endif +#ifdef LTC_MD4 + register_hash (&md4_desc); +#endif +#ifdef LTC_MD5 + register_hash (&md5_desc); +#endif +#ifdef LTC_SHA1 + register_hash (&sha1_desc); +#endif +#ifdef LTC_SHA224 + register_hash (&sha224_desc); +#endif +#ifdef LTC_SHA256 + register_hash (&sha256_desc); +#endif +#ifdef LTC_SHA384 + register_hash (&sha384_desc); +#endif +#ifdef LTC_SHA512 + register_hash (&sha512_desc); +#endif +#ifdef LTC_RIPEMD128 + register_hash (&rmd128_desc); +#endif +#ifdef LTC_RIPEMD160 + register_hash (&rmd160_desc); +#endif +#ifdef LTC_RIPEMD256 + register_hash (&rmd256_desc); +#endif +#ifdef LTC_RIPEMD320 + register_hash (&rmd320_desc); +#endif +#ifdef LTC_WHIRLPOOL + register_hash (&whirlpool_desc); +#endif +#ifdef LTC_CHC_HASH + register_hash(&chc_desc); + if ((err = chc_register(register_cipher(&aes_desc))) != CRYPT_OK) { + fprintf(stderr, "chc_register error: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } +#endif + + +#ifndef LTC_YARROW + #error This demo requires Yarrow. +#endif +register_prng(&yarrow_desc); +#ifdef LTC_FORTUNA +register_prng(&fortuna_desc); +#endif +#ifdef LTC_RC4 +register_prng(&rc4_desc); +#endif +#ifdef LTC_SPRNG +register_prng(&sprng_desc); +#endif + + if ((err = rng_make_prng(128, find_prng("yarrow"), &yarrow_prng, NULL)) != CRYPT_OK) { + fprintf(stderr, "rng_make_prng failed: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + +} + +int time_keysched(void) +{ + unsigned long x, y1; + ulong64 t1, c1; + symmetric_key skey; + int kl; + int (*func) (const unsigned char *, int , int , symmetric_key *); + unsigned char key[MAXBLOCKSIZE]; + + fprintf(stderr, "\n\nKey Schedule Time Trials for the Symmetric Ciphers:\n(Times are cycles per key)\n"); + no_results = 0; + for (x = 0; cipher_descriptor[x].name != NULL; x++) { +#define DO1(k) func(k, kl, 0, &skey); + + func = cipher_descriptor[x].setup; + kl = cipher_descriptor[x].min_key_length; + c1 = (ulong64)-1; + for (y1 = 0; y1 < KTIMES; y1++) { + yarrow_read(key, kl, &yarrow_prng); + t_start(); + DO1(key); + t1 = t_read(); + c1 = (t1 > c1) ? c1 : t1; + } + t1 = c1 - skew; + results[no_results].spd1 = results[no_results].avg = t1; + results[no_results++].id = x; + fprintf(stderr, "."); fflush(stdout); + +#undef DO1 + } + tally_results(0); + + return 0; +} + +int time_cipher(void) +{ + unsigned long x, y1; + ulong64 t1, t2, c1, c2, a1, a2; + symmetric_ECB ecb; + unsigned char key[MAXBLOCKSIZE], pt[4096]; + int err; + + fprintf(stderr, "\n\nECB Time Trials for the Symmetric Ciphers:\n"); + no_results = 0; + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + ecb_start(x, key, cipher_descriptor[x].min_key_length, 0, &ecb); + + /* sanity check on cipher */ + if ((err = cipher_descriptor[x].test()) != CRYPT_OK) { + fprintf(stderr, "\n\nERROR: Cipher %s failed self-test %s\n", cipher_descriptor[x].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + +#define DO1 ecb_encrypt(pt, pt, sizeof(pt), &ecb); +#define DO2 DO1 DO1 + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < 100; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read(); + t2 -= t1; + + c1 = (t1 > c1 ? c1 : t1); + c2 = (t2 > c2 ? c2 : t2); + } + a1 = c2 - c1 - skew; + +#undef DO1 +#undef DO2 +#define DO1 ecb_decrypt(pt, pt, sizeof(pt), &ecb); +#define DO2 DO1 DO1 + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < 100; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read(); + t2 -= t1; + + c1 = (t1 > c1 ? c1 : t1); + c2 = (t2 > c2 ? c2 : t2); + } + a2 = c2 - c1 - skew; + ecb_done(&ecb); + + results[no_results].id = x; + results[no_results].spd1 = a1/(sizeof(pt)/cipher_descriptor[x].block_length); + results[no_results].spd2 = a2/(sizeof(pt)/cipher_descriptor[x].block_length); + results[no_results].avg = (results[no_results].spd1 + results[no_results].spd2+1)/2; + ++no_results; + fprintf(stderr, "."); fflush(stdout); + +#undef DO2 +#undef DO1 + } + tally_results(1); + + return 0; +} + +#ifdef LTC_CBC_MODE +int time_cipher2(void) +{ + unsigned long x, y1; + ulong64 t1, t2, c1, c2, a1, a2; + symmetric_CBC cbc; + unsigned char key[MAXBLOCKSIZE], pt[4096]; + int err; + + fprintf(stderr, "\n\nCBC Time Trials for the Symmetric Ciphers:\n"); + no_results = 0; + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + cbc_start(x, pt, key, cipher_descriptor[x].min_key_length, 0, &cbc); + + /* sanity check on cipher */ + if ((err = cipher_descriptor[x].test()) != CRYPT_OK) { + fprintf(stderr, "\n\nERROR: Cipher %s failed self-test %s\n", cipher_descriptor[x].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + +#define DO1 cbc_encrypt(pt, pt, sizeof(pt), &cbc); +#define DO2 DO1 DO1 + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < 100; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read(); + t2 -= t1; + + c1 = (t1 > c1 ? c1 : t1); + c2 = (t2 > c2 ? c2 : t2); + } + a1 = c2 - c1 - skew; + +#undef DO1 +#undef DO2 +#define DO1 cbc_decrypt(pt, pt, sizeof(pt), &cbc); +#define DO2 DO1 DO1 + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < 100; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read(); + t2 -= t1; + + c1 = (t1 > c1 ? c1 : t1); + c2 = (t2 > c2 ? c2 : t2); + } + a2 = c2 - c1 - skew; + cbc_done(&cbc); + + results[no_results].id = x; + results[no_results].spd1 = a1/(sizeof(pt)/cipher_descriptor[x].block_length); + results[no_results].spd2 = a2/(sizeof(pt)/cipher_descriptor[x].block_length); + results[no_results].avg = (results[no_results].spd1 + results[no_results].spd2+1)/2; + ++no_results; + fprintf(stderr, "."); fflush(stdout); + +#undef DO2 +#undef DO1 + } + tally_results(1); + + return 0; +} +#else +int time_cipher2(void) { fprintf(stderr, "NO CBC\n"); return 0; } +#endif + +#ifdef LTC_CTR_MODE +int time_cipher3(void) +{ + unsigned long x, y1; + ulong64 t1, t2, c1, c2, a1, a2; + symmetric_CTR ctr; + unsigned char key[MAXBLOCKSIZE], pt[4096]; + int err; + + fprintf(stderr, "\n\nCTR Time Trials for the Symmetric Ciphers:\n"); + no_results = 0; + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + ctr_start(x, pt, key, cipher_descriptor[x].min_key_length, 0, CTR_COUNTER_LITTLE_ENDIAN, &ctr); + + /* sanity check on cipher */ + if ((err = cipher_descriptor[x].test()) != CRYPT_OK) { + fprintf(stderr, "\n\nERROR: Cipher %s failed self-test %s\n", cipher_descriptor[x].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + +#define DO1 ctr_encrypt(pt, pt, sizeof(pt), &ctr); +#define DO2 DO1 DO1 + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < 100; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read(); + t2 -= t1; + + c1 = (t1 > c1 ? c1 : t1); + c2 = (t2 > c2 ? c2 : t2); + } + a1 = c2 - c1 - skew; + +#undef DO1 +#undef DO2 +#define DO1 ctr_decrypt(pt, pt, sizeof(pt), &ctr); +#define DO2 DO1 DO1 + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < 100; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read(); + t2 -= t1; + + c1 = (t1 > c1 ? c1 : t1); + c2 = (t2 > c2 ? c2 : t2); + } + a2 = c2 - c1 - skew; + ctr_done(&ctr); + + results[no_results].id = x; + results[no_results].spd1 = a1/(sizeof(pt)/cipher_descriptor[x].block_length); + results[no_results].spd2 = a2/(sizeof(pt)/cipher_descriptor[x].block_length); + results[no_results].avg = (results[no_results].spd1 + results[no_results].spd2+1)/2; + ++no_results; + fprintf(stderr, "."); fflush(stdout); + +#undef DO2 +#undef DO1 + } + tally_results(1); + + return 0; +} +#else +int time_cipher3(void) { fprintf(stderr, "NO CTR\n"); return 0; } +#endif + +#ifdef LTC_LRW_MODE +int time_cipher4(void) +{ + unsigned long x, y1; + ulong64 t1, t2, c1, c2, a1, a2; + symmetric_LRW lrw; + unsigned char key[MAXBLOCKSIZE], pt[4096]; + int err; + + fprintf(stderr, "\n\nLRW Time Trials for the Symmetric Ciphers:\n"); + no_results = 0; + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + if (cipher_descriptor[x].block_length != 16) continue; + lrw_start(x, pt, key, cipher_descriptor[x].min_key_length, key, 0, &lrw); + + /* sanity check on cipher */ + if ((err = cipher_descriptor[x].test()) != CRYPT_OK) { + fprintf(stderr, "\n\nERROR: Cipher %s failed self-test %s\n", cipher_descriptor[x].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + +#define DO1 lrw_encrypt(pt, pt, sizeof(pt), &lrw); +#define DO2 DO1 DO1 + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < 100; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read(); + t2 -= t1; + + c1 = (t1 > c1 ? c1 : t1); + c2 = (t2 > c2 ? c2 : t2); + } + a1 = c2 - c1 - skew; + +#undef DO1 +#undef DO2 +#define DO1 lrw_decrypt(pt, pt, sizeof(pt), &lrw); +#define DO2 DO1 DO1 + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < 100; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read(); + t2 -= t1; + + c1 = (t1 > c1 ? c1 : t1); + c2 = (t2 > c2 ? c2 : t2); + } + a2 = c2 - c1 - skew; + + lrw_done(&lrw); + + results[no_results].id = x; + results[no_results].spd1 = a1/(sizeof(pt)/cipher_descriptor[x].block_length); + results[no_results].spd2 = a2/(sizeof(pt)/cipher_descriptor[x].block_length); + results[no_results].avg = (results[no_results].spd1 + results[no_results].spd2+1)/2; + ++no_results; + fprintf(stderr, "."); fflush(stdout); + +#undef DO2 +#undef DO1 + } + tally_results(1); + + return 0; +} +#else +int time_cipher4(void) { fprintf(stderr, "NO LRW\n"); return 0; } +#endif + + +int time_hash(void) +{ + unsigned long x, y1, len; + ulong64 t1, t2, c1, c2; + hash_state md; + int (*func)(hash_state *, const unsigned char *, unsigned long), err; + unsigned char pt[MAXBLOCKSIZE]; + + + fprintf(stderr, "\n\nHASH Time Trials for:\n"); + no_results = 0; + for (x = 0; hash_descriptor[x].name != NULL; x++) { + + /* sanity check on hash */ + if ((err = hash_descriptor[x].test()) != CRYPT_OK) { + fprintf(stderr, "\n\nERROR: Hash %s failed self-test %s\n", hash_descriptor[x].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + + hash_descriptor[x].init(&md); + +#define DO1 func(&md,pt,len); +#define DO2 DO1 DO1 + + func = hash_descriptor[x].process; + len = hash_descriptor[x].blocksize; + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < TIMES; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read() - t1; + c1 = (t1 > c1) ? c1 : t1; + c2 = (t2 > c2) ? c2 : t2; + } + t1 = c2 - c1 - skew; + t1 = ((t1 * CONST64(1000))) / ((ulong64)hash_descriptor[x].blocksize); + results[no_results].id = x; + results[no_results].spd1 = results[no_results].avg = t1; + ++no_results; + fprintf(stderr, "."); fflush(stdout); +#undef DO2 +#undef DO1 + } + tally_results(2); + + return 0; +} + +#undef MPI +/*#warning you need an mp_rand!!!*/ + +#ifdef MPI +void time_mult(void) +{ + ulong64 t1, t2; + unsigned long x, y; + void *a, *b, *c; + + fprintf(stderr, "Timing Multiplying:\n"); + mp_init_multi(&a,&b,&c,NULL); + for (x = 128/DIGIT_BIT; x <= 1536/DIGIT_BIT; x += 128/DIGIT_BIT) { + mp_rand(&a, x); + mp_rand(&b, x); + +#define DO1 mp_mul(&a, &b, &c); +#define DO2 DO1; DO1; + + t2 = -1; + for (y = 0; y < TIMES; y++) { + t_start(); + t1 = t_read(); + DO2; + t1 = (t_read() - t1)>>1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "%4lu bits: %9llu cycles\n", x*DIGIT_BIT, t2); + } + mp_clear_multi(&a,&b,&c,NULL); + +#undef DO1 +#undef DO2 +} + +void time_sqr(void) +{ + ulong64 t1, t2; + unsigned long x, y; + mp_int a, b; + + fprintf(stderr, "Timing Squaring:\n"); + mp_init_multi(&a,&b,NULL); + for (x = 128/DIGIT_BIT; x <= 1536/DIGIT_BIT; x += 128/DIGIT_BIT) { + mp_rand(&a, x); + +#define DO1 mp_sqr(&a, &b); +#define DO2 DO1; DO1; + + t2 = -1; + for (y = 0; y < TIMES; y++) { + t_start(); + t1 = t_read(); + DO2; + t1 = (t_read() - t1)>>1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "%4lu bits: %9llu cycles\n", x*DIGIT_BIT, t2); + } + mp_clear_multi(&a,&b,NULL); + +#undef DO1 +#undef DO2 +} +#else +void time_mult(void) { fprintf(stderr, "NO MULT\n"); } +void time_sqr(void) { fprintf(stderr, "NO SQR\n"); } +#endif + +void time_prng(void) +{ + ulong64 t1, t2; + unsigned char buf[4096]; + prng_state tprng; + unsigned long x, y; + int err; + + fprintf(stderr, "Timing PRNGs (cycles/byte output, cycles add_entropy (32 bytes) :\n"); + for (x = 0; prng_descriptor[x].name != NULL; x++) { + + /* sanity check on prng */ + if ((err = prng_descriptor[x].test()) != CRYPT_OK) { + fprintf(stderr, "\n\nERROR: PRNG %s failed self-test %s\n", prng_descriptor[x].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + + prng_descriptor[x].start(&tprng); + zeromem(buf, 256); + prng_descriptor[x].add_entropy(buf, 256, &tprng); + prng_descriptor[x].ready(&tprng); + t2 = -1; + +#define DO1 if (prng_descriptor[x].read(buf, 4096, &tprng) != 4096) { fprintf(stderr, "\n\nERROR READ != 4096\n\n"); exit(EXIT_FAILURE); } +#define DO2 DO1 DO1 + for (y = 0; y < 10000; y++) { + t_start(); + t1 = t_read(); + DO2; + t1 = (t_read() - t1)>>1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "%20s: %5llu ", prng_descriptor[x].name, t2>>12); +#undef DO2 +#undef DO1 + +#define DO1 prng_descriptor[x].start(&tprng); prng_descriptor[x].add_entropy(buf, 32, &tprng); prng_descriptor[x].ready(&tprng); prng_descriptor[x].done(&tprng); +#define DO2 DO1 DO1 + for (y = 0; y < 10000; y++) { + t_start(); + t1 = t_read(); + DO2; + t1 = (t_read() - t1)>>1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "%5llu\n", t2); +#undef DO2 +#undef DO1 + + } +} + +#ifdef LTC_MDSA +/* time various DSA operations */ +void time_dsa(void) +{ + dsa_key key; + ulong64 t1, t2; + unsigned long x, y; + int err; +static const struct { + int group, modulus; +} groups[] = { +{ 20, 96 }, +{ 20, 128 }, +{ 24, 192 }, +{ 28, 256 }, +{ 32, 512 } +}; + + for (x = 0; x < (sizeof(groups)/sizeof(groups[0])); x++) { + t2 = 0; + for (y = 0; y < 4; y++) { + t_start(); + t1 = t_read(); + if ((err = dsa_make_key(&yarrow_prng, find_prng("yarrow"), groups[x].group, groups[x].modulus, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\ndsa_make_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; + +#ifdef LTC_PROFILE + t2 <<= 2; + break; +#endif + if (y < 3) { + dsa_free(&key); + } + } + t2 >>= 2; + fprintf(stderr, "DSA-(%lu, %lu) make_key took %15llu cycles\n", (unsigned long)groups[x].group*8, (unsigned long)groups[x].modulus*8, t2); + } +} +#endif + + +#ifdef LTC_MRSA +/* time various RSA operations */ +void time_rsa(void) +{ + rsa_key key; + ulong64 t1, t2; + unsigned char buf[2][2048]; + unsigned long x, y, z, zzz; + int err, zz, stat; + + for (x = 1024; x <= 2048; x += 256) { + t2 = 0; + for (y = 0; y < 4; y++) { + t_start(); + t1 = t_read(); + if ((err = rsa_make_key(&yarrow_prng, find_prng("yarrow"), x/8, 65537, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\nrsa_make_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; + +#ifdef LTC_PROFILE + t2 <<= 2; + break; +#endif + + if (y < 3) { + rsa_free(&key); + } + } + t2 >>= 2; + fprintf(stderr, "RSA-%lu make_key took %15llu cycles\n", x, t2); + + t2 = 0; + for (y = 0; y < 16; y++) { + t_start(); + t1 = t_read(); + z = sizeof(buf[1]); + if ((err = rsa_encrypt_key(buf[0], 32, buf[1], &z, (const unsigned char *)"testprog", 8, &yarrow_prng, + find_prng("yarrow"), find_hash("sha1"), + &key)) != CRYPT_OK) { + fprintf(stderr, "\n\nrsa_encrypt_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; +#ifdef LTC_PROFILE + t2 <<= 4; + break; +#endif + } + t2 >>= 4; + fprintf(stderr, "RSA-%lu encrypt_key took %15llu cycles\n", x, t2); + + t2 = 0; + for (y = 0; y < 2048; y++) { + t_start(); + t1 = t_read(); + zzz = sizeof(buf[0]); + if ((err = rsa_decrypt_key(buf[1], z, buf[0], &zzz, (const unsigned char *)"testprog", 8, find_hash("sha1"), + &zz, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\nrsa_decrypt_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; +#ifdef LTC_PROFILE + t2 <<= 11; + break; +#endif + } + t2 >>= 11; + fprintf(stderr, "RSA-%lu decrypt_key took %15llu cycles\n", x, t2); + + t2 = 0; + for (y = 0; y < 256; y++) { + t_start(); + t1 = t_read(); + z = sizeof(buf[1]); + if ((err = rsa_sign_hash(buf[0], 20, buf[1], &z, &yarrow_prng, + find_prng("yarrow"), find_hash("sha1"), 8, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\nrsa_sign_hash says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; +#ifdef LTC_PROFILE + t2 <<= 8; + break; +#endif + } + t2 >>= 8; + fprintf(stderr, "RSA-%lu sign_hash took %15llu cycles\n", x, t2); + + t2 = 0; + for (y = 0; y < 2048; y++) { + t_start(); + t1 = t_read(); + if ((err = rsa_verify_hash(buf[1], z, buf[0], 20, find_hash("sha1"), 8, &stat, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\nrsa_verify_hash says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + if (stat == 0) { + fprintf(stderr, "\n\nrsa_verify_hash for RSA-%lu failed to verify signature(%lu)\n", x, y); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; +#ifdef LTC_PROFILE + t2 <<= 11; + break; +#endif + } + t2 >>= 11; + fprintf(stderr, "RSA-%lu verify_hash took %15llu cycles\n", x, t2); + fprintf(stderr, "\n\n"); + rsa_free(&key); + } +} +#else +void time_rsa(void) { fprintf(stderr, "NO RSA\n"); } +#endif + +#ifdef MKAT +/* time various KAT operations */ +void time_katja(void) +{ + katja_key key; + ulong64 t1, t2; + unsigned char buf[2][4096]; + unsigned long x, y, z, zzz; + int err, zz; + + for (x = 1024; x <= 2048; x += 256) { + t2 = 0; + for (y = 0; y < 4; y++) { + t_start(); + t1 = t_read(); + if ((err = katja_make_key(&yarrow_prng, find_prng("yarrow"), x/8, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\nkatja_make_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; + + if (y < 3) { + katja_free(&key); + } + } + t2 >>= 2; + fprintf(stderr, "Katja-%lu make_key took %15llu cycles\n", x, t2); + + t2 = 0; + for (y = 0; y < 16; y++) { + t_start(); + t1 = t_read(); + z = sizeof(buf[1]); + if ((err = katja_encrypt_key(buf[0], 32, buf[1], &z, "testprog", 8, &yarrow_prng, + find_prng("yarrow"), find_hash("sha1"), + &key)) != CRYPT_OK) { + fprintf(stderr, "\n\nkatja_encrypt_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; + } + t2 >>= 4; + fprintf(stderr, "Katja-%lu encrypt_key took %15llu cycles\n", x, t2); + + t2 = 0; + for (y = 0; y < 2048; y++) { + t_start(); + t1 = t_read(); + zzz = sizeof(buf[0]); + if ((err = katja_decrypt_key(buf[1], z, buf[0], &zzz, "testprog", 8, find_hash("sha1"), + &zz, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\nkatja_decrypt_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; + } + t2 >>= 11; + fprintf(stderr, "Katja-%lu decrypt_key took %15llu cycles\n", x, t2); + + + katja_free(&key); + } +} +#else +void time_katja(void) { fprintf(stderr, "NO Katja\n"); } +#endif + +#ifdef LTC_MECC +/* time various ECC operations */ +void time_ecc(void) +{ + ecc_key key; + ulong64 t1, t2; + unsigned char buf[2][256]; + unsigned long i, w, x, y, z; + int err, stat; + static unsigned long sizes[] = { +#ifdef ECC112 +112/8, +#endif +#ifdef ECC128 +128/8, +#endif +#ifdef ECC160 +160/8, +#endif +#ifdef ECC192 +192/8, +#endif +#ifdef ECC224 +224/8, +#endif +#ifdef ECC256 +256/8, +#endif +#ifdef ECC384 +384/8, +#endif +#ifdef ECC521 +521/8, +#endif +100000}; + + for (x = sizes[i=0]; x < 100000; x = sizes[++i]) { + t2 = 0; + for (y = 0; y < 256; y++) { + t_start(); + t1 = t_read(); + if ((err = ecc_make_key(&yarrow_prng, find_prng("yarrow"), x, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\necc_make_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; + +#ifdef LTC_PROFILE + t2 <<= 8; + break; +#endif + + if (y < 255) { + ecc_free(&key); + } + } + t2 >>= 8; + fprintf(stderr, "ECC-%lu make_key took %15llu cycles\n", x*8, t2); + + t2 = 0; + for (y = 0; y < 256; y++) { + t_start(); + t1 = t_read(); + z = sizeof(buf[1]); + if ((err = ecc_encrypt_key(buf[0], 20, buf[1], &z, &yarrow_prng, find_prng("yarrow"), find_hash("sha1"), + &key)) != CRYPT_OK) { + fprintf(stderr, "\n\necc_encrypt_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; +#ifdef LTC_PROFILE + t2 <<= 8; + break; +#endif + } + t2 >>= 8; + fprintf(stderr, "ECC-%lu encrypt_key took %15llu cycles\n", x*8, t2); + + t2 = 0; + for (y = 0; y < 256; y++) { + t_start(); + t1 = t_read(); + w = 20; + if ((err = ecc_decrypt_key(buf[1], z, buf[0], &w, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\necc_decrypt_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; +#ifdef LTC_PROFILE + t2 <<= 8; + break; +#endif + } + t2 >>= 8; + fprintf(stderr, "ECC-%lu decrypt_key took %15llu cycles\n", x*8, t2); + + t2 = 0; + for (y = 0; y < 256; y++) { + t_start(); + t1 = t_read(); + z = sizeof(buf[1]); + if ((err = ecc_sign_hash(buf[0], 20, buf[1], &z, &yarrow_prng, + find_prng("yarrow"), &key)) != CRYPT_OK) { + fprintf(stderr, "\n\necc_sign_hash says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; +#ifdef LTC_PROFILE + t2 <<= 8; + break; +#endif + } + t2 >>= 8; + fprintf(stderr, "ECC-%lu sign_hash took %15llu cycles\n", x*8, t2); + + t2 = 0; + for (y = 0; y < 256; y++) { + t_start(); + t1 = t_read(); + if ((err = ecc_verify_hash(buf[1], z, buf[0], 20, &stat, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\necc_verify_hash says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + if (stat == 0) { + fprintf(stderr, "\n\necc_verify_hash for ECC-%lu failed to verify signature(%lu)\n", x*8, y); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; +#ifdef LTC_PROFILE + t2 <<= 8; + break; +#endif + } + t2 >>= 8; + fprintf(stderr, "ECC-%lu verify_hash took %15llu cycles\n", x*8, t2); + + fprintf(stderr, "\n\n"); + ecc_free(&key); + } +} +#else +void time_ecc(void) { fprintf(stderr, "NO ECC\n"); } +#endif + +void time_macs_(unsigned long MAC_SIZE) +{ + unsigned char *buf, key[16], tag[16]; + ulong64 t1, t2; + unsigned long x, z; + int err, cipher_idx, hash_idx; + + fprintf(stderr, "\nMAC Timings (cycles/byte on %luKB blocks):\n", MAC_SIZE); + + buf = XMALLOC(MAC_SIZE*1024); + if (buf == NULL) { + fprintf(stderr, "\n\nout of heap yo\n\n"); + exit(EXIT_FAILURE); + } + + cipher_idx = find_cipher("aes"); + hash_idx = find_hash("sha1"); + + if (cipher_idx == -1 || hash_idx == -1) { + fprintf(stderr, "Warning the MAC tests requires AES and LTC_SHA1 to operate... so sorry\n"); + return; + } + + yarrow_read(buf, MAC_SIZE*1024, &yarrow_prng); + yarrow_read(key, 16, &yarrow_prng); + +#ifdef LTC_OMAC + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = omac_memory(cipher_idx, key, 16, buf, MAC_SIZE*1024, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\n\nomac error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "LTC_OMAC-%s\t\t%9llu\n", cipher_descriptor[cipher_idx].name, t2/(ulong64)(MAC_SIZE*1024)); +#endif + +#ifdef LTC_XCBC + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = xcbc_memory(cipher_idx, key, 16, buf, MAC_SIZE*1024, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\n\nxcbc error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "XCBC-%s\t\t%9llu\n", cipher_descriptor[cipher_idx].name, t2/(ulong64)(MAC_SIZE*1024)); +#endif + +#ifdef LTC_F9_MODE + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = f9_memory(cipher_idx, key, 16, buf, MAC_SIZE*1024, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\n\nF9 error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "F9-%s\t\t\t%9llu\n", cipher_descriptor[cipher_idx].name, t2/(ulong64)(MAC_SIZE*1024)); +#endif + +#ifdef LTC_PMAC + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = pmac_memory(cipher_idx, key, 16, buf, MAC_SIZE*1024, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\n\npmac error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "PMAC-AES\t\t%9llu\n", t2/(ulong64)(MAC_SIZE*1024)); +#endif + +#ifdef LTC_PELICAN + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = pelican_memory(key, 16, buf, MAC_SIZE*1024, tag)) != CRYPT_OK) { + fprintf(stderr, "\n\npelican error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "LTC_PELICAN \t\t%9llu\n", t2/(ulong64)(MAC_SIZE*1024)); +#endif + +#ifdef LTC_HMAC + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = hmac_memory(hash_idx, key, 16, buf, MAC_SIZE*1024, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\n\nhmac error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "LTC_HMAC-%s\t\t%9llu\n", hash_descriptor[hash_idx].name, t2/(ulong64)(MAC_SIZE*1024)); +#endif + + XFREE(buf); +} + +void time_macs(void) +{ + time_macs_(1); + time_macs_(4); + time_macs_(32); +} + +void time_encmacs_(unsigned long MAC_SIZE) +{ + unsigned char *buf, IV[16], key[16], tag[16]; + ulong64 t1, t2; + unsigned long x, z; + int err, cipher_idx; + symmetric_key skey; + + fprintf(stderr, "\nENC+MAC Timings (zero byte AAD, 16 byte IV, cycles/byte on %luKB blocks):\n", MAC_SIZE); + + buf = XMALLOC(MAC_SIZE*1024); + if (buf == NULL) { + fprintf(stderr, "\n\nout of heap yo\n\n"); + exit(EXIT_FAILURE); + } + + cipher_idx = find_cipher("aes"); + + yarrow_read(buf, MAC_SIZE*1024, &yarrow_prng); + yarrow_read(key, 16, &yarrow_prng); + yarrow_read(IV, 16, &yarrow_prng); + +#ifdef LTC_EAX_MODE + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = eax_encrypt_authenticate_memory(cipher_idx, key, 16, IV, 16, NULL, 0, buf, MAC_SIZE*1024, buf, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\nEAX error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "EAX \t\t\t%9llu\n", t2/(ulong64)(MAC_SIZE*1024)); +#endif + +#ifdef LTC_OCB_MODE + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = ocb_encrypt_authenticate_memory(cipher_idx, key, 16, IV, buf, MAC_SIZE*1024, buf, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\nOCB error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "OCB \t\t\t%9llu\n", t2/(ulong64)(MAC_SIZE*1024)); +#endif + +#ifdef LTC_CCM_MODE + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = ccm_memory(cipher_idx, key, 16, NULL, IV, 16, NULL, 0, buf, MAC_SIZE*1024, buf, tag, &z, CCM_ENCRYPT)) != CRYPT_OK) { + fprintf(stderr, "\nCCM error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "CCM (no-precomp) \t%9llu\n", t2/(ulong64)(MAC_SIZE*1024)); + + cipher_descriptor[cipher_idx].setup(key, 16, 0, &skey); + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = ccm_memory(cipher_idx, key, 16, &skey, IV, 16, NULL, 0, buf, MAC_SIZE*1024, buf, tag, &z, CCM_ENCRYPT)) != CRYPT_OK) { + fprintf(stderr, "\nCCM error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "CCM (precomp) \t\t%9llu\n", t2/(ulong64)(MAC_SIZE*1024)); + cipher_descriptor[cipher_idx].done(&skey); +#endif + +#ifdef LTC_GCM_MODE + t2 = -1; + for (x = 0; x < 100; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = gcm_memory(cipher_idx, key, 16, IV, 16, NULL, 0, buf, MAC_SIZE*1024, buf, tag, &z, GCM_ENCRYPT)) != CRYPT_OK) { + fprintf(stderr, "\nGCM error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "GCM (no-precomp)\t%9llu\n", t2/(ulong64)(MAC_SIZE*1024)); + + { + gcm_state gcm +#ifdef LTC_GCM_TABLES_SSE2 +__attribute__ ((aligned (16))) +#endif +; + + if ((err = gcm_init(&gcm, cipher_idx, key, 16)) != CRYPT_OK) { fprintf(stderr, "gcm_init: %s\n", error_to_string(err)); exit(EXIT_FAILURE); } + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = gcm_reset(&gcm)) != CRYPT_OK) { + fprintf(stderr, "\nGCM error[%d]... %s\n", __LINE__, error_to_string(err)); + exit(EXIT_FAILURE); + } + if ((err = gcm_add_iv(&gcm, IV, 16)) != CRYPT_OK) { + fprintf(stderr, "\nGCM error[%d]... %s\n", __LINE__, error_to_string(err)); + exit(EXIT_FAILURE); + } + if ((err = gcm_add_aad(&gcm, NULL, 0)) != CRYPT_OK) { + fprintf(stderr, "\nGCM error[%d]... %s\n", __LINE__, error_to_string(err)); + exit(EXIT_FAILURE); + } + if ((err = gcm_process(&gcm, buf, MAC_SIZE*1024, buf, GCM_ENCRYPT)) != CRYPT_OK) { + fprintf(stderr, "\nGCM error[%d]... %s\n", __LINE__, error_to_string(err)); + exit(EXIT_FAILURE); + } + + if ((err = gcm_done(&gcm, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\nGCM error[%d]... %s\n", __LINE__, error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "GCM (precomp)\t\t%9llu\n", t2/(ulong64)(MAC_SIZE*1024)); + } + +#endif + +} + +void time_encmacs(void) +{ + time_encmacs_(1); + time_encmacs_(4); + time_encmacs_(32); +} + +/* $Source: /cvs/libtom/libtomcrypt/testprof/x86_prof.c,v $ */ +/* $Revision: 1.58 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/core/mm/sub.mk b/core/mm/sub.mk new file mode 100644 index 00000000000..e69de29bb2d diff --git a/core/sub.mk b/core/sub.mk new file mode 100644 index 00000000000..04559ec9548 --- /dev/null +++ b/core/sub.mk @@ -0,0 +1,4 @@ +subdirs-y += kernel +subdirs-y += mm +subdirs-y += tee +subdirs-y += drivers diff --git a/core/tee/sub.mk b/core/tee/sub.mk new file mode 100644 index 00000000000..805970da185 --- /dev/null +++ b/core/tee/sub.mk @@ -0,0 +1,31 @@ +srcs-y += tee_svc.c +cflags-tee_svc.c-y += -Wno-format -Wno-declaration-after-statement +cflags-tee_svc.c-y += -Wno-unused-parameter +cflags-tee_svc.c-y += -Wno-format-nonliteral -Wno-format-security + + +srcs-y += tee_svc_cryp.c +cflags-tee_svc_cryp.c-y += -Wno-declaration-after-statement +cflags-tee_svc_cryp.c-y += -Wno-unused-parameter +cflags-tee_svc_cryp.c-y += -Wno-cast-align + +srcs-y += tee_acipher.c +cflags-tee_acipher.c-y += -Wno-unused-parameter + +srcs-y += tee_authenc.c +cflags-tee_authenc.c-y += -Wno-unused-parameter + +srcs-y += tee_mac.c +cflags-tee_mac.c-y += -Wno-unused-parameter + +srcs-y += tee_rpmb.c +cflags-tee_rpmb.c-y += -Wno-unused-parameter + +srcs-y += tee_cipher.c +srcs-y += tee_fs.c +srcs-y += tee_hash.c +srcs-y += tee_obj.c +srcs-y += tee_pobj.c +srcs-y += tee_rpmb_fs.c +srcs-y += tee_svc_storage.c +srcs-y += tee_time_generic.c diff --git a/core/tee/tee_acipher.c b/core/tee/tee_acipher.c new file mode 100644 index 00000000000..ca92ff2b8fc --- /dev/null +++ b/core/tee/tee_acipher.c @@ -0,0 +1,508 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +TEE_Result tee_acipher_gen_rsa_keys(rsa_key *ltc_key, size_t key_size) +{ + TEE_Result res; + rsa_key ltc_tmp_key; + int ltc_res; + + /* Get the rsa key */ + ltc_res = rsa_make_key( + 0, tee_ltc_get_rng_mpa(), key_size/8, 65537, <c_tmp_key); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_PARAMETERS; + } else if ((size_t)mp_count_bits(ltc_tmp_key.N) != key_size) { + rsa_free(<c_tmp_key); + res = TEE_ERROR_BAD_PARAMETERS; + } else { + /* copy the key */ + ltc_mp.copy(ltc_tmp_key.e, ltc_key->e); + ltc_mp.copy(ltc_tmp_key.d, ltc_key->d); + ltc_mp.copy(ltc_tmp_key.N, ltc_key->N); + ltc_mp.copy(ltc_tmp_key.p, ltc_key->p); + ltc_mp.copy(ltc_tmp_key.q, ltc_key->q); + ltc_mp.copy(ltc_tmp_key.qP, ltc_key->qP); + ltc_mp.copy(ltc_tmp_key.dP, ltc_key->dP); + ltc_mp.copy(ltc_tmp_key.dQ, ltc_key->dQ); + + /* free the tempory key */ + rsa_free(<c_tmp_key); + res = TEE_SUCCESS; + } + return res; +} + +TEE_Result tee_acipher_gen_dh_keys(dh_key *ltc_key, void *q, size_t xbits) +{ + TEE_Result res; + dh_key ltc_tmp_key; + int ltc_res; + + /* Get the dh key */ + ltc_tmp_key.g = ltc_key->g; + ltc_tmp_key.p = ltc_key->p; + ltc_res = dh_make_key( + 0, tee_ltc_get_rng_mpa(), + q, xbits, <c_tmp_key); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_PARAMETERS; + } else { + ltc_mp.copy(ltc_tmp_key.y, ltc_key->y); + ltc_mp.copy(ltc_tmp_key.x, ltc_key->x); + + /* free the tempory key */ + dh_free(<c_tmp_key); + res = TEE_SUCCESS; + } + return res; +} + +TEE_Result tee_acipher_gen_dsa_keys(dsa_key *ltc_key, size_t key_size) +{ + TEE_Result res; + dsa_key ltc_tmp_key; + size_t group_size, modulus_size = key_size/8; + int ltc_res; + + if (modulus_size <= 128) + group_size = 20; + else if (modulus_size <= 256) + group_size = 30; + else if (modulus_size <= 384) + group_size = 35; + else + group_size = 40; + + /* Get the dsa key */ + ltc_res = dsa_make_key( + 0, tee_ltc_get_rng_mpa(), + group_size, modulus_size, <c_tmp_key); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_PARAMETERS; + } else if ((size_t)mp_count_bits(ltc_tmp_key.p) != key_size) { + dsa_free(<c_tmp_key); + res = TEE_ERROR_BAD_PARAMETERS; + } else { + /* copy the key */ + ltc_mp.copy(ltc_tmp_key.g, ltc_key->g); + ltc_mp.copy(ltc_tmp_key.p, ltc_key->p); + ltc_mp.copy(ltc_tmp_key.q, ltc_key->q); + ltc_mp.copy(ltc_tmp_key.y, ltc_key->y); + ltc_mp.copy(ltc_tmp_key.x, ltc_key->x); + + /* free the tempory key */ + dsa_free(<c_tmp_key); + res = TEE_SUCCESS; + } + return res; +} + +TEE_Result tee_derive_dh_shared_secret( + dh_key *private_key, void *public_key, void *secret) +{ + int err; + err = dh_shared_secret(private_key, public_key, secret); + + return ((err == CRYPT_OK) ? TEE_SUCCESS : TEE_ERROR_BAD_PARAMETERS); +} + +TEE_Result tee_acipher_rsadorep( + rsa_key *ltc_key, + const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) +{ + TEE_Result res = TEE_SUCCESS; + uint8_t *buf = NULL; + uint32_t blen, offset; + int ltc_res; + + /* + * Use a temporary buffer since we don't know exactly how large the + * required size of the out buffer without doing a partial decrypt. + * We know the upper bound though. + */ + blen = (mpa_StaticTempVarSizeInU32(LTC_MAX_BITS_PER_VARIABLE)) * + sizeof(uint32_t); + buf = malloc(blen); + if (buf == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + ltc_res = rsa_exptmod( + src, src_len, /* input message and length */ + buf, (unsigned long *)(&blen), /* decrypted message and len */ + ltc_key->type, + ltc_key); + if (ltc_res != CRYPT_OK) { + EMSG("rsa_exptmod() returned %d\n", ltc_res); + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if (*dst_len < blen) { + *dst_len = blen; + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + res = TEE_SUCCESS; + if (ltc_key->type == PK_PUBLIC) { + /* encrypting / signing */ + *dst_len = blen; + offset = 0; + } else { + /* remove the zero-padding */ + offset = 0; + while ((buf[offset] == 0) && (offset < blen)) + offset++; + *dst_len = blen - offset; + } + memcpy(dst, (char *)buf + offset, *dst_len); + +out: + if (buf) + free(buf); + + return res; +} + +TEE_Result tee_acipher_rsaes_decrypt( + uint32_t algo, rsa_key *ltc_key, const uint8_t *label, size_t label_len, + const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) +{ + TEE_Result res = TEE_SUCCESS; + void *buf = NULL; + uint32_t blen; + int ltc_hashindex, ltc_res, ltc_stat, ltc_rsa_algo; + size_t mod_size; + + /* Get the algorithm */ + res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); + if (res != TEE_SUCCESS) { + EMSG("tee_algo_to_ltc_hashindex() returned %d\n", (int)res); + goto out; + } + + if (algo == TEE_ALG_RSAES_PKCS1_V1_5) { + mod_size = ltc_mp.unsigned_size((void *)(ltc_key->N)); + /* + * Use a temporary buffer since we don't know exactly how large + * the required size of the out buffer without doing a partial + * decrypt. We know the upper bound though. + */ + blen = mod_size - 11; + ltc_rsa_algo = LTC_LTC_PKCS_1_V1_5; + } else { + /* + * Use a temporary buffer since we don't know exactly how + * large the required size of the out buffer without doing a + * partial decrypt. We know the upper bound though: the length + * of the decoded message is lower than the encrypted message + */ + blen = src_len; + ltc_rsa_algo = LTC_LTC_PKCS_1_OAEP; + } + + buf = malloc(blen); + if (buf == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + ltc_res = rsa_decrypt_key_ex( + src, src_len, /* input message and length */ + buf, (unsigned long *)(&blen), /* decrypted message and len */ + ((label_len == 0) ? 0 : label), label_len, /* label and len */ + ltc_hashindex, /* hash index, based on the algo */ + ltc_rsa_algo, + <c_stat, + ltc_key); + if ((ltc_res != CRYPT_OK) || (ltc_stat != 1)) { + EMSG("rsa_decrypt_key_ex() returned %d and %d\n", + ltc_res, ltc_stat); + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if (*dst_len < blen) { + *dst_len = blen; + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + res = TEE_SUCCESS; + *dst_len = blen; + memcpy(dst, buf, blen); + +out: + if (buf) + free(buf); + + return res; +} + +TEE_Result tee_acipher_rsaes_encrypt( + uint32_t algo, rsa_key *ltc_key, const uint8_t *label, size_t label_len, + const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) +{ + TEE_Result res; + uint32_t mod_size; + int ltc_hashindex, ltc_res, ltc_rsa_algo; + + mod_size = ltc_mp.unsigned_size((void *)(ltc_key->N)); + if (*dst_len < mod_size) { + *dst_len = mod_size; + return TEE_ERROR_SHORT_BUFFER; + } + *dst_len = mod_size; + + /* Get the algorithm */ + res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); + if (res != TEE_SUCCESS) { + EMSG("tee_algo_to_ltc_hashindex() returned %d\n", (int)res); + goto out; + } + + if (algo == TEE_ALG_RSAES_PKCS1_V1_5) + ltc_rsa_algo = LTC_LTC_PKCS_1_V1_5; + else + ltc_rsa_algo = LTC_LTC_PKCS_1_OAEP; + + ltc_res = rsa_encrypt_key_ex( + src, src_len, /* input message and length */ + dst, (unsigned long *)(dst_len), /* encrypted message and len */ + label, label_len, /* label and length */ + 0, tee_ltc_get_rng_mpa(), + ltc_hashindex, /* hash index, based on the algo */ + ltc_rsa_algo, + ltc_key); + if (ltc_res != CRYPT_OK) { + EMSG("rsa_encrypt_key_ex() returned %d\n", ltc_res); + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + res = TEE_SUCCESS; + +out: + return res; +} + + +TEE_Result tee_acipher_rsassa_sign( + uint32_t algo, rsa_key *ltc_key, int salt_len, + const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len) +{ + TEE_Result res; + size_t hash_size; + size_t mod_size; + int ltc_res, ltc_rsa_algo, ltc_hashindex; + + switch (algo) { + case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: + ltc_rsa_algo = LTC_LTC_PKCS_1_V1_5; + break; + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: + ltc_rsa_algo = LTC_LTC_PKCS_1_PSS; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + ltc_res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_BAD_PARAMETERS; + + res = + tee_hash_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo), &hash_size); + if (res != TEE_SUCCESS) + return res; + + if (msg_len != hash_size) + return TEE_ERROR_BAD_PARAMETERS; + + mod_size = ltc_mp.unsigned_size((void *)(ltc_key->N)); + + if (*sig_len < mod_size) { + *sig_len = mod_size; + return TEE_ERROR_SHORT_BUFFER; + } + + *sig_len = mod_size; + + ltc_res = rsa_sign_hash_ex( + msg, msg_len, + sig, (unsigned long *)(&sig_len), + ltc_rsa_algo, + 0, tee_ltc_get_rng_mpa(), + ltc_hashindex, + salt_len, + ltc_key); + + if (ltc_res != CRYPT_OK) { + EMSG("rsa_encrypt_key_ex() returned %d\n", ltc_res); + return TEE_ERROR_BAD_PARAMETERS; + } + + return TEE_SUCCESS; +} + +TEE_Result tee_acipher_rsassa_verify( + uint32_t algo, rsa_key *ltc_key, int salt_len, + const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len) +{ + TEE_Result res; + uint32_t bigint_size; + int stat, ltc_hashindex, ltc_res, ltc_rsa_algo; + + bigint_size = ltc_mp.unsigned_size(ltc_key->N); + if (sig_len < bigint_size) + return TEE_ERROR_SIGNATURE_INVALID; + + + /* Get the algorithm */ + res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); + if (res != TEE_SUCCESS) { + EMSG("tee_algo_to_ltc_hashindex() returned %d\n", (int)res); + return res; + } + + switch (algo) { + case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: + ltc_rsa_algo = LTC_LTC_PKCS_1_V1_5; + break; + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: + ltc_rsa_algo = LTC_LTC_PKCS_1_PSS; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + ltc_res = rsa_verify_hash_ex( + sig, sig_len, + msg, msg_len, + ltc_rsa_algo, ltc_hashindex, + salt_len, + &stat, + ltc_key); + if ((ltc_res != CRYPT_OK) || (stat != 1)) { + EMSG("rsa_encrypt_key_ex() returned %d\n", ltc_res); + return TEE_ERROR_SIGNATURE_INVALID; + } + + return TEE_SUCCESS; +} + +TEE_Result tee_acipher_dsa_sign( + uint32_t algo, dsa_key *ltc_key, + const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len) +{ + TEE_Result res; + int ltc_res; + void *r, *s; + if (*sig_len < 2 * mp_unsigned_bin_size(ltc_key->q)) { + *sig_len = 2 * mp_unsigned_bin_size(ltc_key->q); + return TEE_ERROR_SHORT_BUFFER; + } + + ltc_res = mp_init_multi(&r, &s, NULL); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_OUT_OF_MEMORY; + ltc_res = dsa_sign_hash_raw( + msg, msg_len, r, s, 0, tee_ltc_get_rng_mpa(), ltc_key); + + if (ltc_res == CRYPT_OK) { + *sig_len = 2 * mp_unsigned_bin_size(ltc_key->q); + memset(sig, 0, *sig_len); + mp_to_unsigned_bin( + r, + (uint8_t *)sig + *sig_len/2 - mp_unsigned_bin_size(r)); + mp_to_unsigned_bin( + s, + (uint8_t *)sig + *sig_len - mp_unsigned_bin_size(s)); + res = TEE_SUCCESS; + } else { + res = TEE_ERROR_GENERIC; + } + + mp_clear_multi(r, s, NULL); + return res; +} + +TEE_Result tee_acipher_dsa_verify( + uint32_t algo, dsa_key *ltc_key, + const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len) +{ + TEE_Result res; + int ltc_stat, ltc_res; + void *r, *s; + + ltc_res = mp_init_multi(&r, &s, NULL); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_OUT_OF_MEMORY; + mp_read_unsigned_bin(r, (uint8_t *)sig, sig_len/2); + mp_read_unsigned_bin(s, (uint8_t *)sig + sig_len/2, sig_len/2); + ltc_res = dsa_verify_hash_raw(r, s, msg, msg_len, <c_stat, ltc_key); + mp_clear_multi(r, s, NULL); + + if ((ltc_res == CRYPT_OK) && (ltc_stat == 1)) + res = TEE_SUCCESS; + else + res = TEE_ERROR_GENERIC; + + mp_clear_multi(r, s, NULL); + return res; +} diff --git a/core/tee/tee_authenc.c b/core/tee/tee_authenc.c new file mode 100644 index 00000000000..eec7b183077 --- /dev/null +++ b/core/tee/tee_authenc.c @@ -0,0 +1,450 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "tee_ltc_wrapper.h" + +/* + * From Libtomcrypt documentation + * CCM is a NIST proposal for encrypt + authenticate that is centered around + * using AES (or any 16-byte cipher) as a primitive. Unlike EAX and OCB mode, + * it is only meant for packet mode where the length of the input is known in + * advance. Since it is a packet mode function, CCM only has one function that + * performs the protocol + */ + +#define TEE_CCM_KEY_MAX_LENGTH 32 +#define TEE_CCM_NONCE_MAX_LENGTH 13 +#define TEE_CCM_TAG_MAX_LENGTH 32 + +struct ccm_state { + uint8_t key[TEE_CCM_KEY_MAX_LENGTH]; /* the key */ + size_t key_len; /* the key length */ + uint8_t nonce[TEE_CCM_NONCE_MAX_LENGTH]; /* the nonce */ + size_t nonce_len; /* nonce length */ + uint8_t tag[TEE_CCM_TAG_MAX_LENGTH]; /* computed tag on last data */ + size_t tag_len; /* tag length */ + size_t aad_len; + size_t payload_len; /* final expected payload length */ + uint8_t *payload; /* the payload */ + size_t current_payload_len; /* the current payload length */ + uint8_t *res_payload; /* result with the whole payload */ + int ltc_cipherindex; /* the libtomcrypt cipher index */ + uint8_t *header; /* the header (aad) */ + size_t header_len; /* header length */ +}; + +TEE_Result tee_authenc_get_ctx_size(uint32_t algo, size_t *size) +{ + switch (algo) { + case TEE_ALG_AES_CCM: + *size = sizeof(struct ccm_state); + break; + case TEE_ALG_AES_GCM: + *size = sizeof(gcm_state); + break; + default: + return TEE_ERROR_NOT_SUPPORTED; + } + return TEE_SUCCESS; +} + +TEE_Result tee_authenc_init( + void *ctx, uint32_t algo, TEE_OperationMode mode, const uint8_t *key, + size_t key_len, const uint8_t *nonce, + size_t nonce_len, size_t tag_len, size_t aad_len, size_t payload_len) +{ + TEE_Result res; + int ltc_res; + int ltc_cipherindex; + unsigned char *payload, *res_payload; + struct ccm_state *ccm; + + res = tee_algo_to_ltc_cipherindex(algo, <c_cipherindex); + if (res != TEE_SUCCESS) + return TEE_ERROR_NOT_SUPPORTED; + switch (algo) { + case TEE_ALG_AES_CCM: + /* Check the key length */ + if ((!key) || (key_len > TEE_CCM_KEY_MAX_LENGTH)) + return TEE_ERROR_BAD_PARAMETERS; + + /* check the nonce */ + if (nonce_len > TEE_CCM_NONCE_MAX_LENGTH) + return TEE_ERROR_BAD_PARAMETERS; + + /* check the tag len */ + if ((tag_len < 4) || + (tag_len > TEE_CCM_TAG_MAX_LENGTH) || + (tag_len % 2 != 0)) + return TEE_ERROR_NOT_SUPPORTED; + + /* allocate payload */ + payload = malloc(payload_len + TEE_CCM_KEY_MAX_LENGTH); + if (!payload) + return TEE_ERROR_OUT_OF_MEMORY; + res_payload = malloc(payload_len + TEE_CCM_KEY_MAX_LENGTH); + if (!res_payload) { + free(payload); + return TEE_ERROR_OUT_OF_MEMORY; + } + + /* initialize the structure */ + ccm = (struct ccm_state *)ctx; + memset(ccm, 0, sizeof(struct ccm_state)); + memcpy(ccm->key, key, key_len); + ccm->key_len = key_len; /* the key length */ + if (nonce && nonce_len) { + memcpy(ccm->nonce, nonce, nonce_len); + ccm->nonce_len = nonce_len; + } else { + ccm->nonce_len = 0; + } + ccm->tag_len = tag_len; + ccm->aad_len = aad_len; + ccm->payload_len = payload_len; + ccm->payload = payload; + ccm->res_payload = res_payload; + ccm->ltc_cipherindex = ltc_cipherindex; + + if (ccm->aad_len) { + ccm->header = malloc(ccm->aad_len); + if (!ccm->header) { + free(payload); + free(res_payload); + return TEE_ERROR_OUT_OF_MEMORY; + } + } + + /* memset the payload to 0 that will be used for padding */ + memset(ccm->payload, 0, payload_len + TEE_CCM_KEY_MAX_LENGTH); + break; + + case TEE_ALG_AES_GCM: + /* reset the state */ + ltc_res = gcm_init( + (gcm_state *)ctx, ltc_cipherindex, key, key_len); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_BAD_STATE; + + /* Add the IV */ + ltc_res = gcm_add_iv((gcm_state *)ctx, nonce, nonce_len); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_BAD_STATE; + break; + + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + return TEE_SUCCESS; +} + +TEE_Result tee_authenc_update_aad( + void *ctx, uint32_t algo, TEE_OperationMode mode, + const uint8_t *data, size_t len) +{ + struct ccm_state *ccm; + int ltc_res; + + switch (algo) { + case TEE_ALG_AES_CCM: + ccm = (struct ccm_state *)ctx; + if (ccm->aad_len < ccm->header_len + len) + return TEE_ERROR_BAD_PARAMETERS; + memcpy(ccm->header + ccm->header_len, data, len); + ccm->header_len += len; + break; + + case TEE_ALG_AES_GCM: + /* Add the AAD (note: aad can be NULL if aadlen == 0) */ + ltc_res = gcm_add_aad((gcm_state *)ctx, data, len); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_BAD_STATE; + break; + + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + return TEE_SUCCESS; +} + +TEE_Result tee_authenc_update_payload( + void *ctx, uint32_t algo, TEE_OperationMode mode, + const uint8_t *src_data, size_t src_len, uint8_t *dst_data) +{ + TEE_Result res; + int ltc_res, dir; + struct ccm_state *ccm; + unsigned char *pt, *ct; /* the plain and the cipher text */ + + if (mode == TEE_MODE_ENCRYPT) { + pt = (unsigned char *)src_data; + ct = dst_data; + } else { + pt = dst_data; + ct = (unsigned char *)src_data; + } + + switch (algo) { + case TEE_ALG_AES_CCM: + /* Check aad has been correctly added */ + ccm = (struct ccm_state *)ctx; + if (ccm->aad_len != ccm->header_len) + return TEE_ERROR_BAD_STATE; + + /* + * check we do not add more data than what was defined at + * the init + */ + if (ccm->current_payload_len + src_len > ccm->payload_len) + return TEE_ERROR_BAD_PARAMETERS; + memcpy(ccm->payload + ccm->current_payload_len, + src_data, src_len); + ccm->current_payload_len += src_len; + + dir = (mode == TEE_MODE_ENCRYPT ? CCM_ENCRYPT : CCM_DECRYPT); + ltc_res = ccm_memory( + ccm->ltc_cipherindex, + ccm->key, ccm->key_len, + 0, /* not presecheduled */ + ccm->nonce, ccm->nonce_len, + ccm->header, ccm->header_len, + pt, src_len, ct, + ccm->tag, (unsigned long *)&ccm->tag_len, dir); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_BAD_STATE; + break; + + case TEE_ALG_AES_GCM: + /* aad is optional ==> add one without length */ + if (((gcm_state *)ctx)->mode == LTC_GCM_MODE_IV) { + res = tee_authenc_update_aad(ctx, algo, mode, 0, 0); + if (res != TEE_SUCCESS) + return res; + } + + /* process the data */ + dir = (mode == TEE_MODE_ENCRYPT ? GCM_ENCRYPT : GCM_DECRYPT); + ltc_res = gcm_process((gcm_state *)ctx, pt, src_len, ct, dir); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_BAD_STATE; + break; + + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + return TEE_SUCCESS; +} + +TEE_Result tee_authenc_enc_final( + void *ctx, uint32_t algo, const uint8_t *src_data, + size_t src_len, uint8_t *dst_data, + uint8_t *dst_tag, size_t *dst_tag_len) +{ + TEE_Result res, final_res = TEE_ERROR_MAC_INVALID; + struct ccm_state *ccm; + size_t digest_size; + int ltc_res; + int init_len; + + /* Check the resulting buffer is not too short */ + res = tee_cipher_get_block_size(algo, &digest_size); + if (res != TEE_SUCCESS) { + final_res = res; + goto out; + } + + switch (algo) { + case TEE_ALG_AES_CCM: + ccm = (struct ccm_state *)ctx; + + init_len = ccm->current_payload_len; + if (src_len) { + memcpy(ccm->payload + ccm->current_payload_len, + src_data, src_len); + ccm->current_payload_len += src_len; + } + + if (ccm->payload_len != ccm->current_payload_len) + return TEE_ERROR_BAD_PARAMETERS; + + ltc_res = ccm_memory( + ccm->ltc_cipherindex, + ccm->key, ccm->key_len, + 0, /* not presecheduled */ + ccm->nonce, ccm->nonce_len, + ccm->header, ccm->header_len, + ccm->payload, ccm->current_payload_len, + ccm->res_payload, + dst_tag, (unsigned long *)dst_tag_len, CCM_ENCRYPT); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_BAD_STATE; + + if (src_len) + memcpy(dst_data, ccm->res_payload + init_len, src_len); + break; + + case TEE_ALG_AES_GCM: + /* Finalize the remaining buffer */ + res = tee_authenc_update_payload( + ctx, algo, TEE_MODE_ENCRYPT, + src_data, src_len, dst_data); + if (res != TEE_SUCCESS) { + final_res = res; + goto out; + } + + /* Process the last buffer, if any */ + ltc_res = gcm_done( + (gcm_state *)ctx, + dst_tag, (unsigned long *)dst_tag_len); + if (ltc_res != CRYPT_OK) + goto out; + break; + + default: + return TEE_ERROR_NOT_SUPPORTED; + } + final_res = TEE_SUCCESS; + +out: + return final_res; +} + +TEE_Result tee_authenc_dec_final( + void *ctx, uint32_t algo, const uint8_t *src_data, + size_t src_len, uint8_t *dst_data, const uint8_t *tag, size_t tag_len) +{ + TEE_Result res = TEE_ERROR_BAD_STATE; + struct ccm_state *ccm; + int ltc_res; + uint8_t *dst_tag; + size_t dst_len, init_len; + + res = tee_cipher_get_block_size(algo, &dst_len); + if (res != TEE_SUCCESS) + return res; + + if (tag_len == 0) + return TEE_ERROR_SHORT_BUFFER; + dst_len = tag_len; + dst_tag = malloc(tag_len); + if (!dst_tag) + return TEE_ERROR_OUT_OF_MEMORY; + + switch (algo) { + case TEE_ALG_AES_CCM: + ccm = (struct ccm_state *)ctx; + + init_len = ccm->current_payload_len; + if (src_len) { + memcpy(ccm->payload + ccm->current_payload_len, + src_data, src_len); + ccm->current_payload_len += src_len; + } + + if (ccm->payload_len != ccm->current_payload_len) + return TEE_ERROR_BAD_PARAMETERS; + + ltc_res = ccm_memory( + ccm->ltc_cipherindex, + ccm->key, ccm->key_len, + 0, /* not presecheduled */ + ccm->nonce, ccm->nonce_len, + ccm->header, ccm->header_len, + ccm->res_payload, + ccm->current_payload_len, ccm->payload, + dst_tag, (unsigned long *)&tag_len, CCM_DECRYPT); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_BAD_STATE; + + if (src_len) + memcpy(dst_data, ccm->res_payload + init_len, src_len); + break; + + + case TEE_ALG_AES_GCM: + /* Process the last buffer, if any */ + res = tee_authenc_update_payload( + ctx, algo, TEE_MODE_DECRYPT, + src_data, src_len, dst_data); + if (res != TEE_SUCCESS) + goto out; + + /* Finalize the authentification */ + ltc_res = gcm_done( + (gcm_state *)ctx, + dst_tag, (unsigned long *)&tag_len); + if (ltc_res != CRYPT_OK) + goto out; + break; + + default: + res = TEE_ERROR_NOT_SUPPORTED; + goto out; + } + + if (memcmp(dst_tag, tag, tag_len) != 0) + res = TEE_ERROR_MAC_INVALID; + else + res = TEE_SUCCESS; + +out: + if (dst_tag) + free(dst_tag); + return res; +} + +void tee_authenc_final(void *ctx, uint32_t algo) +{ + struct ccm_state *ccm; + + switch (algo) { + case TEE_ALG_AES_CCM: + ccm = (struct ccm_state *)ctx; + if (ccm->payload) + free(ccm->payload); + if (ccm->res_payload) + free(ccm->res_payload); + ccm->payload_len = 0; + if (ccm->header) + free(ccm->header); + ccm->aad_len = 0; + ccm->header_len = 0; + break; + case TEE_ALG_AES_GCM: + gcm_reset((gcm_state *)ctx); + break; + default: + break; + } +} diff --git a/core/tee/tee_cipher.c b/core/tee/tee_cipher.c new file mode 100644 index 00000000000..43a0745752e --- /dev/null +++ b/core/tee/tee_cipher.c @@ -0,0 +1,496 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tee_ltc_wrapper.h" +#include +#include + +/* From libtomcrypt doc: + * Ciphertext stealing is a method of dealing with messages + * in CBC mode which are not a multiple of the block + * length. This is accomplished by encrypting the last + * ciphertext block in ECB mode, and XOR'ing the output + * against the last partial block of plaintext. LibTomCrypt + * does not support this mode directly but it is fairly + * easy to emulate with a call to the cipher's + * ecb encrypt() callback function. + * The more sane way to deal with partial blocks is to pad + * them with zeroes, and then use CBC normally + */ + +/* + * From Global Platform: CTS = CBC-CS3 + */ + +struct symmetric_CTS { + symmetric_ECB ecb; + symmetric_CBC cbc; +}; + +TEE_Result tee_cipher_get_block_size(uint32_t algo, size_t *size) +{ + TEE_Result res; + int ltc_cipherindex; + + res = tee_algo_to_ltc_cipherindex(algo, <c_cipherindex); + if (res != TEE_SUCCESS) + return TEE_ERROR_NOT_SUPPORTED; + + *size = cipher_descriptor[ltc_cipherindex].block_length; + return TEE_SUCCESS; +} + +TEE_Result tee_cipher_get_ctx_size(uint32_t algo, size_t *size) +{ + switch (algo) { + case TEE_ALG_AES_ECB_NOPAD: + *size = sizeof(symmetric_ECB); + break; + case TEE_ALG_AES_CBC_NOPAD: + *size = sizeof(symmetric_CBC); + break; + case TEE_ALG_AES_CTR: + *size = sizeof(symmetric_CTR); + break; + case TEE_ALG_AES_CTS: + *size = sizeof(struct symmetric_CTS); + break; + case TEE_ALG_AES_XTS: + *size = sizeof(symmetric_xts); + break; + case TEE_ALG_DES_ECB_NOPAD: + *size = sizeof(symmetric_ECB); + break; + case TEE_ALG_DES_CBC_NOPAD: + *size = sizeof(symmetric_CBC); + break; + case TEE_ALG_DES3_ECB_NOPAD: + *size = sizeof(symmetric_ECB); + break; + case TEE_ALG_DES3_CBC_NOPAD: + *size = sizeof(symmetric_CBC); + break; + + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + return TEE_SUCCESS; +} + +TEE_Result tee_cipher_init(void *ctx, uint32_t algo, + TEE_OperationMode mode, const uint8_t *key, + size_t key_len) +{ + return tee_cipher_init3(ctx, algo, mode, key, key_len, NULL, 0, NULL, + 0); +} + +TEE_Result tee_cipher_init2(void *ctx, uint32_t algo, + TEE_OperationMode mode, const uint8_t *key, + size_t key_len, const uint8_t *iv, size_t iv_len) +{ + return tee_cipher_init3(ctx, algo, mode, key, key_len, NULL, 0, iv, + iv_len); +} + +static void get_des2_key( + const uint8_t *key, size_t key_len, + uint8_t *key_intermediate, + uint8_t **real_key, size_t *real_key_len) +{ + if (key_len == 16) { + /* + * This corresponds to a 2DES key. The 2DES encryption + * algorithm is similar to 3DES. Both perform and + * encryption step, then a decryption step, followed + * by another encryption step (EDE). However 2DES uses + * the same key for both of the encryption (E) steps. + */ + memcpy(key_intermediate, key, 16); + memcpy(key_intermediate+16, key, 8); + *real_key = key_intermediate; + *real_key_len = 24; + } else { + *real_key = (uint8_t *)key; + *real_key_len = key_len; + } +} + +TEE_Result tee_cipher_init3(void *ctx, uint32_t algo, + TEE_OperationMode mode, const uint8_t *key1, + size_t key1_len, const uint8_t *key2, + size_t key2_len, const uint8_t *iv, size_t iv_len) +{ + TEE_Result res; + int ltc_res, ltc_cipherindex; + uint8_t *real_key, key_array[24]; + size_t real_key_len; + struct symmetric_CTS *cts; + + res = tee_algo_to_ltc_cipherindex(algo, <c_cipherindex); + if (res != TEE_SUCCESS) + return TEE_ERROR_NOT_SUPPORTED; + + switch (algo) { + case TEE_ALG_AES_ECB_NOPAD: + case TEE_ALG_DES_ECB_NOPAD: + ltc_res = ecb_start( + ltc_cipherindex, key1, key1_len, + 0, (symmetric_ECB *)ctx); + break; + + case TEE_ALG_DES3_ECB_NOPAD: + /* either des3 or des2, depending on the size of the key */ + get_des2_key(key1, key1_len, key_array, + &real_key, &real_key_len); + ltc_res = ecb_start( + ltc_cipherindex, real_key, real_key_len, + 0, (symmetric_ECB *)ctx); + break; + + case TEE_ALG_AES_CBC_NOPAD: + case TEE_ALG_DES_CBC_NOPAD: + if (iv_len != + (size_t)cipher_descriptor[ltc_cipherindex].block_length) + return TEE_ERROR_BAD_PARAMETERS; + ltc_res = cbc_start( + ltc_cipherindex, iv, key1, key1_len, + 0, (symmetric_CBC *)ctx); + break; + + case TEE_ALG_DES3_CBC_NOPAD: + /* either des3 or des2, depending on the size of the key */ + get_des2_key(key1, key1_len, key_array, + &real_key, &real_key_len); + if (iv_len != + (size_t)cipher_descriptor[ltc_cipherindex].block_length) + return TEE_ERROR_BAD_PARAMETERS; + ltc_res = cbc_start( + ltc_cipherindex, iv, real_key, real_key_len, + 0, (symmetric_CBC *)ctx); + break; + + case TEE_ALG_AES_CTR: + if (iv_len != + (size_t)cipher_descriptor[ltc_cipherindex].block_length) + return TEE_ERROR_BAD_PARAMETERS; + ltc_res = ctr_start( + ltc_cipherindex, iv, key1, key1_len, + 0, CTR_COUNTER_BIG_ENDIAN, (symmetric_CTR *)ctx); + break; + + case TEE_ALG_AES_CTS: + cts = (struct symmetric_CTS *)ctx; + res = tee_cipher_init3( + (void *)(&(cts->ecb)), + TEE_ALG_AES_ECB_NOPAD, mode, + key1, key1_len, key2, key2_len, iv, iv_len); + if (res != TEE_SUCCESS) + return res; + res = tee_cipher_init3( + (void *)(&(cts->cbc)), + TEE_ALG_AES_CBC_NOPAD, mode, + key1, key1_len, key2, key2_len, iv, iv_len); + if (res != TEE_SUCCESS) + return res; + ltc_res = CRYPT_OK; + break; + + case TEE_ALG_AES_XTS: + if (key1_len != key2_len) + return TEE_ERROR_BAD_PARAMETERS; + ltc_res = xts_start( + ltc_cipherindex, key1, key2, key1_len, + 0, (symmetric_xts *)ctx); + break; + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + if (ltc_res == CRYPT_OK) + return TEE_SUCCESS; + else + return TEE_ERROR_BAD_STATE; +} + +TEE_Result tee_cipher_update(void *ctx, uint32_t algo, + TEE_OperationMode mode, bool last_block, + const uint8_t *data, size_t len, uint8_t *dst) +{ + TEE_Result res; + int ltc_res = CRYPT_OK; + size_t block_size; + uint8_t tmp_block[64], tmp2_block[64]; + int nb_blocks, len_last_block; + struct symmetric_CTS *cts; + + /* + * Check that the block contains the correct number of data, apart + * for the last block in some XTS / CTR / XTS mode + */ + res = tee_cipher_get_block_size(algo, &block_size); + if (res != TEE_SUCCESS) + return res; + if ((len % block_size) != 0) { + if (!last_block) + return TEE_ERROR_BAD_PARAMETERS; + + switch (algo) { + case TEE_ALG_AES_ECB_NOPAD: + case TEE_ALG_DES_ECB_NOPAD: + case TEE_ALG_DES3_ECB_NOPAD: + case TEE_ALG_AES_CBC_NOPAD: + case TEE_ALG_DES_CBC_NOPAD: + case TEE_ALG_DES3_CBC_NOPAD: + return TEE_ERROR_BAD_PARAMETERS; + + case TEE_ALG_AES_CTR: + case TEE_ALG_AES_XTS: + case TEE_ALG_AES_CTS: + /* + * These modes doesn't require padding for the last + * block. + * + * This isn't entirely true, both XTS and CTS can only + * encrypt minimum one block and also they need at least + * one complete block in the last update to finish the + * encryption. The algorithms are supposed to detect + * that, we're only making sure that all data fed up to + * that point consists of complete blocks. + */ + break; + + default: + return TEE_ERROR_NOT_SUPPORTED; + } + } + + switch (algo) { + case TEE_ALG_AES_ECB_NOPAD: + case TEE_ALG_DES_ECB_NOPAD: + case TEE_ALG_DES3_ECB_NOPAD: + if (mode == TEE_MODE_ENCRYPT) + ltc_res = ecb_encrypt(data, dst, len, (symmetric_ECB *)ctx); + else + ltc_res = ecb_decrypt(data, dst, len, (symmetric_ECB *)ctx); + break; + + case TEE_ALG_AES_CBC_NOPAD: + case TEE_ALG_DES_CBC_NOPAD: + case TEE_ALG_DES3_CBC_NOPAD: + if (mode == TEE_MODE_ENCRYPT) + ltc_res = cbc_encrypt(data, dst, len, (symmetric_CBC *)ctx); + else + ltc_res = cbc_decrypt(data, dst, len, (symmetric_CBC *)ctx); + break; + + case TEE_ALG_AES_CTR: + if (mode == TEE_MODE_ENCRYPT) + ltc_res = ctr_encrypt(data, dst, len, (symmetric_CTR *)ctx); + else + ltc_res = ctr_decrypt(data, dst, len, (symmetric_CTR *)ctx); + break; + + case TEE_ALG_AES_XTS: + return TEE_ERROR_NOT_SUPPORTED; +/* +if (mode == TEE_MODE_ENCRYPT) { + ltc_res = xts_encrypt(data, dst, len, (symmetric_xts *)ctx); +} else { + ltc_res = xts_decrypt(data, dst, len, (symmetric_xts *)ctx); +} +*/ + break; + + case TEE_ALG_AES_CTS: + /* + * From http://en.wikipedia.org/wiki/Ciphertext_stealing + * CBC ciphertext stealing encryption using a standard + * CBC interface: + * 1. Pad the last partial plaintext block with 0. + * 2. Encrypt the whole padded plaintext using the + * standard CBC mode. + * 3. Swap the last two ciphertext blocks. + * 4. Truncate the ciphertext to the length of the + * original plaintext. + * + * CBC ciphertext stealing decryption using a standard + * CBC interface + * 1. Dn = Decrypt (K, Cn-1). Decrypt the second to last + * ciphertext block. + * 2. Cn = Cn || Tail (Dn, B-M). Pad the ciphertext to the + * nearest multiple of the block size using the last + * B-M bits of block cipher decryption of the + * second-to-last ciphertext block. + * 3. Swap the last two ciphertext blocks. + * 4. Decrypt the (modified) ciphertext using the standard + * CBC mode. + * 5. Truncate the plaintext to the length of the original + * ciphertext. + */ + cts = (struct symmetric_CTS *)ctx; + if (!last_block) + return tee_cipher_update( + &cts->cbc, TEE_ALG_AES_CBC_NOPAD, mode, + last_block, data, len, dst); + + /* Compute the last block length and check constraints */ + if (block_size > 64) + return TEE_ERROR_BAD_STATE; + nb_blocks = ((len + block_size - 1) / block_size); + if (nb_blocks < 2) + return TEE_ERROR_BAD_STATE; + len_last_block = len % block_size; + if (len_last_block == 0) + len_last_block = block_size; + + if (mode == TEE_MODE_ENCRYPT) { + memcpy(tmp_block, + data + ((nb_blocks - 1) * block_size), + len_last_block); + memset(tmp_block + len_last_block, + 0, + block_size - len_last_block); + + res = tee_cipher_update( + &cts->cbc, TEE_ALG_AES_CBC_NOPAD, mode, 0, + data, (nb_blocks - 1) * block_size, dst); + if (res != TEE_SUCCESS) + return res; + + memcpy(dst + (nb_blocks - 1) * block_size, + dst + (nb_blocks - 2) * block_size, + len_last_block); + + res = tee_cipher_update( + &cts->cbc, TEE_ALG_AES_CBC_NOPAD, mode, 0, + tmp_block, + block_size, + dst + (nb_blocks - 2) * block_size); + if (res != TEE_SUCCESS) + return res; + } else { + /* 1. Decrypt the second to last ciphertext block */ + res = tee_cipher_update( + &cts->ecb, TEE_ALG_AES_ECB_NOPAD, mode, 0, + data + (nb_blocks - 2) * block_size, + block_size, + tmp2_block); + if (res != TEE_SUCCESS) + return res; + + /* 2. Cn = Cn || Tail (Dn, B-M) */ + memcpy(tmp_block, + data + ((nb_blocks - 1) * block_size), + len_last_block); + memcpy(tmp_block + len_last_block, + tmp2_block + len_last_block, + block_size - len_last_block); + + /* 3. Swap the last two ciphertext blocks */ + /* done by passing the correct buffers in step 4. */ + + /* 4. Decrypt the (modified) ciphertext */ + if (nb_blocks > 2) { + res = tee_cipher_update( + &cts->cbc, TEE_ALG_AES_CBC_NOPAD, + mode, 0, + data, + (nb_blocks - 2) * block_size, + dst); + if (res != TEE_SUCCESS) + return res; + } + + res = tee_cipher_update( + &cts->cbc, TEE_ALG_AES_CBC_NOPAD, mode, 0, + tmp_block, + block_size, + dst + ((nb_blocks - 2) * block_size)); + if (res != TEE_SUCCESS) + return res; + + res = tee_cipher_update( + &cts->cbc, TEE_ALG_AES_CBC_NOPAD, mode, 0, + data + ((nb_blocks - 2) * block_size), + block_size, + tmp_block); + if (res != TEE_SUCCESS) + return res; + + /* 5. Truncate the plaintext */ + memcpy(dst + (nb_blocks - 1) * block_size, + tmp_block, + len_last_block); + break; + } + break; + + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + if (ltc_res == CRYPT_OK) + return TEE_SUCCESS; + else + return TEE_ERROR_BAD_STATE; +} + +void tee_cipher_final(void *ctx, uint32_t algo) +{ + switch (algo) { + case TEE_ALG_AES_ECB_NOPAD: + case TEE_ALG_DES_ECB_NOPAD: + case TEE_ALG_DES3_ECB_NOPAD: + ecb_done((symmetric_ECB *)ctx); + break; + + case TEE_ALG_AES_CBC_NOPAD: + case TEE_ALG_DES_CBC_NOPAD: + case TEE_ALG_DES3_CBC_NOPAD: + cbc_done((symmetric_CBC *)ctx); + break; + + case TEE_ALG_AES_CTR: + ctr_done((symmetric_CTR *)ctx); + break; + + case TEE_ALG_AES_XTS: + xts_done((symmetric_xts *)ctx); + break; + + case TEE_ALG_AES_CTS: + cbc_done(&(((struct symmetric_CTS *)ctx)->cbc)); + ecb_done(&(((struct symmetric_CTS *)ctx)->ecb)); + break; + + default: + /* TEE_ERROR_NOT_SUPPORTED; */ + break; + } +} diff --git a/core/tee/tee_fs.c b/core/tee/tee_fs.c new file mode 100644 index 00000000000..f8a3e49263c --- /dev/null +++ b/core/tee/tee_fs.c @@ -0,0 +1,553 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + + +#include "tee_api_defines.h" +#include + +/* TEE FS operation */ +#define TEE_FS_OPEN 1 +#define TEE_FS_CLOSE 2 +#define TEE_FS_READ 3 +#define TEE_FS_WRITE 4 +#define TEE_FS_SEEK 5 +#define TEE_FS_UNLINK 6 +#define TEE_FS_RENAME 7 +#define TEE_FS_TRUNC 8 +#define TEE_FS_MKDIR 9 +#define TEE_FS_OPENDIR 10 +#define TEE_FS_CLOSEDIR 11 +#define TEE_FS_READDIR 12 +#define TEE_FS_RMDIR 13 +#define TEE_FS_ACCESS 14 + +#define TEE_FS_MODE_NONE 0 +#define TEE_FS_MODE_IN 1 +#define TEE_FS_MODE_OUT 2 + +struct tee_fs_rpc { + int op; + int flags; + int arg; + int fd; + uint32_t len; + int res; +}; + +struct tee_fs_fd { + int nw_fd; /* normal world fd */ + uint32_t flags; + uint32_t fp; /* file pointer offset */ + uint32_t len; +}; + +struct tee_fs_dir { + uint32_t nw_dir; + struct tee_fs_dirent d; +}; + +/* + * File descriptors are generated based on virtual address + * of the effective descriptors in RAM. As all descriptor structures + * are allocated from teecore "malloc" support, descriptor IDs + * are generated as the offset from malloc pool start address to + * the effective descriptor structure in RAM. + * Could use another way. this one is quick and reliable. + */ + +/* Get file descriptor from tee_fs_fd pointer */ +#define TEE_FS_GET_FD(_x) ((uint32_t)(_x) - TEE_HEAP_START0) +/* Get tee_fs_fd pointer from file descriptor */ +#define TEE_FS_GET_FDP(_x) ((void *)((uint32_t)(_x) + TEE_HEAP_START0)) + +static int tee_fs_send_cmd(struct tee_fs_rpc *bf_cmd, void *data, uint32_t len, + uint32_t mode) +{ + struct teesmc32_arg *arg; + struct teesmc32_param *params; + const size_t num_params = 1; + paddr_t pharg = 0; + paddr_t phpayload = 0; + paddr_t cookie = 0; + struct tee_fs_rpc *bf; + int res = -1; + + pharg = thread_rpc_alloc_arg(TEESMC32_GET_ARG_SIZE(num_params)); + thread_st_rpc_alloc_payload(sizeof(struct tee_fs_rpc) + len, + &phpayload, &cookie); + if (!pharg || !phpayload) + goto exit; + + if (!TEE_ALIGNMENT_IS_OK(pharg, struct teesmc32_arg) || + !TEE_ALIGNMENT_IS_OK(phpayload, struct tee_fs_rpc)) + goto exit; + + if (core_pa2va(pharg, (uint32_t *)&arg) || + core_pa2va(phpayload, (uint32_t *)&bf)) + goto exit; + + arg->cmd = TEE_RPC_FS; + arg->ret = TEE_ERROR_GENERIC; + arg->num_params = num_params; + params = TEESMC32_GET_PARAMS(arg); + params[0].attr = TEESMC_ATTR_TYPE_MEMREF_INOUT | + (TEESMC_ATTR_CACHE_I_WRITE_THR | + TEESMC_ATTR_CACHE_O_WRITE_THR) << + TEESMC_ATTR_CACHE_SHIFT; + + params[0].u.memref.buf_ptr = phpayload; + params[0].u.memref.size = sizeof(struct tee_fs_rpc) + len; + + /* fill in parameters */ + *bf = *bf_cmd; + + if (mode & TEE_FS_MODE_IN) + memcpy((void *)(bf + 1), data, len); + + thread_rpc_cmd(pharg); + /* update result */ + *bf_cmd = *bf; + if (arg->ret != TEE_SUCCESS) + goto exit; + + if (mode & TEE_FS_MODE_OUT) { + uint32_t olen = MIN(len, bf->len); + + memcpy(data, (void *)(bf + 1), olen); + } + + res = 0; + +exit: + thread_rpc_free_arg(pharg); + thread_st_rpc_free_payload(cookie); + return res; +} + +int tee_fs_open(const char *file, int flags, ...) +{ + int res = -1; + size_t len; + struct tee_fs_fd *fd = NULL; + struct tee_fs_rpc head = { 0 }; + + len = strlen(file) + 1; + if (len > TEE_FS_NAME_MAX) + goto exit; + + /* fill in parameters */ + head.op = TEE_FS_OPEN; + head.flags = flags; + head.fd = 0; + + res = tee_fs_send_cmd(&head, (void *)file, len, TEE_FS_MODE_IN); + if (res) + goto exit; + + res = head.res; + + if (res == -1) + goto exit; + + fd = (struct tee_fs_fd *)malloc(sizeof(struct tee_fs_fd)); + if (fd == NULL) + goto exit; + + /* init internal status */ + fd->nw_fd = head.fd; + fd->flags = flags; + + /* return fd */ + res = TEE_FS_GET_FD(fd); + +exit: + if (res == -1) + free(fd); + + return res; +} + +int tee_fs_close(int fd) +{ + int res = -1; + struct tee_fs_fd *fdp = TEE_FS_GET_FDP(fd); + struct tee_fs_rpc head = { 0 }; + + if (fdp == NULL) + return -1; + + /* fill in parameters */ + head.op = TEE_FS_CLOSE; + head.fd = fdp->nw_fd; + + res = tee_fs_send_cmd(&head, NULL, 0, TEE_FS_MODE_NONE); + if (res) + goto exit; + + res = head.res; + +exit: + free(fdp); + + return res; +} + +int tee_fs_read(int fd, void *buf, size_t len) +{ + int res = -1; + struct tee_fs_fd *fdp = TEE_FS_GET_FDP(fd); + struct tee_fs_rpc head = { 0 }; + + if (len == 0) { + res = 0; + goto exit; + } + + if (fdp == NULL || buf == NULL) { + res = -1; + goto exit; + } + + /* fill in parameters */ + head.op = TEE_FS_READ; + head.fd = fdp->nw_fd; + head.len = (uint32_t) len; + + res = tee_fs_send_cmd(&head, (void *)buf, len, TEE_FS_MODE_OUT); + if (res) + goto exit; + + res = head.res; + +exit: + return res; +} + +int tee_fs_write(int fd, const void *buf, size_t len) +{ + int res = -1; + struct tee_fs_fd *fdp = TEE_FS_GET_FDP(fd); + struct tee_fs_rpc head = { 0 }; + + if (len == 0) { + res = 0; + goto exit; + } + + if (buf == NULL) { + res = -1; + goto exit; + } + + if (fdp == NULL) { + res = -1; + goto exit; + } + + /* fill in parameters */ + head.op = TEE_FS_WRITE; + head.fd = fdp->nw_fd; + head.len = len; + + res = tee_fs_send_cmd(&head, (void *)buf, len, TEE_FS_MODE_IN); + if (res) + goto exit; + + res = head.res; + +exit: + return res; +} + +tee_fs_off_t tee_fs_lseek(int fd, tee_fs_off_t offset, int whence) +{ + tee_fs_off_t res = -1; + struct tee_fs_fd *fdp = TEE_FS_GET_FDP(fd); + struct tee_fs_rpc head = { 0 }; + + /* fill in parameters */ + head.op = TEE_FS_SEEK; + head.fd = fdp->nw_fd; + head.arg = offset; + head.flags = whence; + + res = tee_fs_send_cmd(&head, NULL, 0, TEE_FS_MODE_NONE); + if (res) + goto exit; + + res = head.res; + +exit: + return res; +} + +int tee_fs_rename(const char *old, const char *new) +{ + int res = -1; + char *tmp = NULL; + struct tee_fs_rpc head = { 0 }; + size_t len_old = strlen(old) + 1; + size_t len_new = strlen(new) + 1; + size_t len = len_old + len_new; + + if (len > TEE_FS_NAME_MAX) + goto exit; + + tmp = malloc(len); + if (!tmp) + goto exit; + memcpy(tmp, old, len_old); + memcpy(tmp + len_old, new, len_new); + + head.op = TEE_FS_RENAME; + + res = tee_fs_send_cmd(&head, tmp, len, TEE_FS_MODE_IN); + if (res) + goto exit; + + res = head.res; + +exit: + free(tmp); + return res; +} + +int tee_fs_unlink(const char *file) +{ + int res = -1; + struct tee_fs_rpc head = { 0 }; + + size_t len = strlen(file) + 1; + if (len > TEE_FS_NAME_MAX) + goto exit; + + head.op = TEE_FS_UNLINK; + + res = tee_fs_send_cmd(&head, (void *)file, len, TEE_FS_MODE_IN); + if (res) + goto exit; + + res = head.res; + +exit: + return res; +} + +int tee_fs_ftruncate(int fd, tee_fs_off_t length) +{ + int res = -1; + struct tee_fs_fd *fdp = TEE_FS_GET_FDP(fd); + struct tee_fs_rpc head = { 0 }; + + if (fdp == NULL) + goto exit; + + head.op = TEE_FS_TRUNC; + head.fd = fdp->nw_fd; + head.arg = length; + + res = tee_fs_send_cmd(&head, NULL, 0, TEE_FS_MODE_NONE); + if (res) + goto exit; + + res = head.res; + +exit: + return res; +} + +int tee_fs_mkdir(const char *path, tee_fs_mode_t mode) +{ + int res = -1; + struct tee_fs_rpc head = { 0 }; + uint32_t len; + + len = strlen(path) + 1; + if (len > TEE_FS_NAME_MAX) + goto exit; + + head.op = TEE_FS_MKDIR; + head.flags = mode; + + res = tee_fs_send_cmd(&head, (void *)path, len, TEE_FS_MODE_IN); + if (res) + goto exit; + + res = head.res; + +exit: + return res; +} + +tee_fs_dir *tee_fs_opendir(const char *name) +{ + struct tee_fs_rpc head = { 0 }; + uint32_t len; + struct tee_fs_dir *dir = NULL; + + len = strlen(name) + 1; + if (len > TEE_FS_NAME_MAX) + goto exit; + + head.op = TEE_FS_OPENDIR; + + if (tee_fs_send_cmd(&head, (void *)name, len, TEE_FS_MODE_IN)) + goto exit; + + if (head.res == 0) + goto exit; + + dir = malloc(sizeof(struct tee_fs_dir)); + if (dir == NULL) + goto exit; + + dir->nw_dir = head.res; + dir->d.d_name = NULL; + +exit: + return dir; +} + +int tee_fs_closedir(tee_fs_dir *d) +{ + int res = -1; + struct tee_fs_rpc head = { 0 }; + + if (d == NULL) { + res = 0; + goto exit; + } + + head.op = TEE_FS_CLOSEDIR; + head.arg = (int)d->nw_dir; + + res = tee_fs_send_cmd(&head, NULL, 0, TEE_FS_MODE_NONE); + if (res) + goto exit; + + res = head.res; + +exit: + if (d) + free(d->d.d_name); + free(d); + + return res; +} + +struct tee_fs_dirent *tee_fs_readdir(tee_fs_dir *d) +{ + struct tee_fs_dirent *res = NULL; + struct tee_fs_rpc head = { 0 }; + char fname[TEE_FS_NAME_MAX + 1]; + + if (!d) + goto exit; + + head.op = TEE_FS_READDIR; + head.arg = (int)d->nw_dir; + + if (tee_fs_send_cmd(&head, fname, sizeof(fname), TEE_FS_MODE_OUT)) + goto exit; + + if (!head.res) { + free(d->d.d_name); + d->d.d_name = NULL; + goto exit; + } + + if (!head.len || head.len > sizeof(fname)) + goto exit; + + fname[head.len - 1] = '\0'; /* make sure it's zero terminated */ + free(d->d.d_name); + d->d.d_name = strdup(fname); + if (!d->d.d_name) + goto exit; + + res = &d->d; +exit: + return res; +} + +int tee_fs_rmdir(const char *name) +{ + int res = -1; + struct tee_fs_rpc head = { 0 }; + uint32_t len; + + len = strlen(name) + 1; + if (len > TEE_FS_NAME_MAX) + goto exit; + + head.op = TEE_FS_RMDIR; + + res = tee_fs_send_cmd(&head, (void *)name, len, TEE_FS_MODE_IN); + if (res) + goto exit; + + res = head.res; + +exit: + return res; +} + +int tee_fs_access(const char *name, int mode) +{ + int res = -1; + struct tee_fs_rpc head = { 0 }; + uint32_t len; + + len = strlen(name) + 1; + if (len > TEE_FS_NAME_MAX) + goto exit; + + head.op = TEE_FS_ACCESS; + head.flags = mode; + + res = tee_fs_send_cmd(&head, (void *)name, len, TEE_FS_MODE_IN); + if (res) + goto exit; + + res = head.res; + +exit: + return res; +} diff --git a/core/tee/tee_hash.c b/core/tee/tee_hash.c new file mode 100644 index 00000000000..7c516524cdb --- /dev/null +++ b/core/tee/tee_hash.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "tee_ltc_wrapper.h" + +#define MAX_DIGEST 64 + +TEE_Result tee_hash_get_digest_size(uint32_t algo, size_t *size) +{ + int ltc_res, ltc_hashindex; + + ltc_res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); + if (ltc_res != TEE_SUCCESS) + return TEE_ERROR_NOT_SUPPORTED; + + *size = hash_descriptor[ltc_hashindex].hashsize; + return TEE_SUCCESS; +} + +TEE_Result tee_hash_get_ctx_size(uint32_t algo, size_t *size) +{ + switch (algo) { + case TEE_ALG_MD5: + case TEE_ALG_SHA224: + case TEE_ALG_SHA1: + case TEE_ALG_SHA256: + case TEE_ALG_SHA384: + case TEE_ALG_SHA512: + case TEE_ALG_HMAC_MD5: + case TEE_ALG_HMAC_SHA224: + case TEE_ALG_HMAC_SHA1: + case TEE_ALG_HMAC_SHA256: + case TEE_ALG_HMAC_SHA384: + case TEE_ALG_HMAC_SHA512: + *size = sizeof(hash_state); + break; + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + return TEE_SUCCESS; +} + +TEE_Result tee_hash_init(void *ctx, uint32_t algo) +{ + int ltc_res, ltc_hashindex; + + ltc_res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); + if (ltc_res != TEE_SUCCESS) + return TEE_ERROR_NOT_SUPPORTED; + + if (hash_descriptor[ltc_hashindex].init(ctx) == CRYPT_OK) + return TEE_SUCCESS; + else + return TEE_ERROR_BAD_STATE; +} + +TEE_Result tee_hash_update(void *ctx, uint32_t algo, + const uint8_t *data, size_t len) +{ + int ltc_res, ltc_hashindex; + + ltc_res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); + if (ltc_res != TEE_SUCCESS) + return TEE_ERROR_NOT_SUPPORTED; + + if (hash_descriptor[ltc_hashindex].process(ctx, data, len) == CRYPT_OK) + return TEE_SUCCESS; + else + return TEE_ERROR_BAD_STATE; +} + +TEE_Result tee_hash_final(void *ctx, uint32_t algo, uint8_t *digest, size_t len) +{ + int ltc_res, ltc_hashindex; + size_t hash_size; + uint8_t block_digest[MAX_DIGEST], *tmp_digest; + + ltc_res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); + if (ltc_res != TEE_SUCCESS) + return TEE_ERROR_NOT_SUPPORTED; + + if (len == 0) + return TEE_ERROR_BAD_PARAMETERS; + + hash_size = hash_descriptor[ltc_hashindex].hashsize; + if ((hash_size < len) || (hash_size > MAX_DIGEST)) { + /* + * Caller is asking for more bytes than the computation + * will produce ... might be something wrong + */ + return TEE_ERROR_BAD_PARAMETERS; + } + + if (hash_size > len) { + /* use a tempory buffer */ + tmp_digest = block_digest; + } else { + tmp_digest = digest; + } + + if (hash_descriptor[ltc_hashindex].done(ctx, tmp_digest) == CRYPT_OK) { + if (hash_size > len) + memcpy(digest, tmp_digest, len); + } else { + return TEE_ERROR_BAD_STATE; + } + + return TEE_SUCCESS; +} + +TEE_Result tee_hash_createdigest( + uint32_t algo, + const uint8_t *data, size_t datalen, + uint8_t *digest, size_t digestlen) +{ + TEE_Result res = TEE_ERROR_BAD_STATE; + void *ctx = NULL; + size_t ctxsize; + + if (tee_hash_get_ctx_size(algo, &ctxsize) != TEE_SUCCESS) { + res = TEE_ERROR_NOT_SUPPORTED; + goto out; + } + + ctx = malloc(ctxsize); + if (ctx == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + if (tee_hash_init(ctx, algo) != TEE_SUCCESS) + goto out; + + if (datalen != 0) { + if (tee_hash_update(ctx, algo, data, datalen) != TEE_SUCCESS) + goto out; + } + + if (tee_hash_final(ctx, algo, digest, digestlen) != TEE_SUCCESS) + goto out; + + res = TEE_SUCCESS; + +out: + if (ctx) + free(ctx); + + return res; +} + +TEE_Result tee_hash_check( + uint32_t algo, + const uint8_t *hash, size_t hash_size, + const uint8_t *data, size_t data_size) +{ + TEE_Result res; + uint8_t digest[MAX_DIGEST]; + size_t digestlen; + + res = tee_hash_get_digest_size(algo, &digestlen); + if (res != TEE_SUCCESS) + return TEE_ERROR_BAD_PARAMETERS; + if ((hash_size == 0) || + (digestlen < hash_size) || + (digestlen > MAX_DIGEST)) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_hash_createdigest(algo, data, data_size, digest, digestlen); + if (res != TEE_SUCCESS) + return res; + + if (memcmp(digest, hash, hash_size) != 0) + return TEE_ERROR_SECURITY; + + return TEE_SUCCESS; +} diff --git a/core/tee/tee_mac.c b/core/tee/tee_mac.c new file mode 100644 index 00000000000..5142beb3295 --- /dev/null +++ b/core/tee/tee_mac.c @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include + +/* + * CBC-MAC is not implemented in Libtomcrypt + * This is implemented here as being the plain text which is encoded with IV=0. + * Result of the CBC-MAC is the last 16-bytes cipher. + */ + +#define CBCMAC_MAX_BLOCK_LEN 16 +struct cbc_state { + symmetric_CBC cbc; + uint8_t block[CBCMAC_MAX_BLOCK_LEN]; + uint8_t digest[CBCMAC_MAX_BLOCK_LEN]; + size_t current_block_len, block_len; + int is_computed; +}; + +TEE_Result tee_mac_get_digest_size(uint32_t algo, size_t *size) +{ + TEE_Result res; + + switch (algo) { + case TEE_ALG_HMAC_MD5: + case TEE_ALG_HMAC_SHA224: + case TEE_ALG_HMAC_SHA1: + case TEE_ALG_HMAC_SHA256: + case TEE_ALG_HMAC_SHA384: + case TEE_ALG_HMAC_SHA512: + res = tee_hash_get_digest_size(algo, size); + return res; + case TEE_ALG_AES_CBC_MAC_NOPAD: + case TEE_ALG_AES_CBC_MAC_PKCS5: + case TEE_ALG_AES_CMAC: + case TEE_ALG_DES_CBC_MAC_NOPAD: + case TEE_ALG_DES_CBC_MAC_PKCS5: + case TEE_ALG_DES3_CBC_MAC_NOPAD: + case TEE_ALG_DES3_CBC_MAC_PKCS5: + res = tee_cipher_get_block_size(algo, size); + return res; + + default: + return TEE_ERROR_NOT_SUPPORTED; + } +} + +TEE_Result tee_mac_get_ctx_size(uint32_t algo, size_t *size) +{ + switch (algo) { + case TEE_ALG_HMAC_MD5: + case TEE_ALG_HMAC_SHA224: + case TEE_ALG_HMAC_SHA1: + case TEE_ALG_HMAC_SHA256: + case TEE_ALG_HMAC_SHA384: + case TEE_ALG_HMAC_SHA512: + *size = sizeof(hmac_state); + break; + + case TEE_ALG_AES_CBC_MAC_NOPAD: + case TEE_ALG_AES_CBC_MAC_PKCS5: + case TEE_ALG_DES_CBC_MAC_NOPAD: + case TEE_ALG_DES_CBC_MAC_PKCS5: + case TEE_ALG_DES3_CBC_MAC_NOPAD: + case TEE_ALG_DES3_CBC_MAC_PKCS5: + *size = sizeof(struct cbc_state); + break; + + case TEE_ALG_AES_CMAC: + *size = sizeof(omac_state); + break; + + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + return TEE_SUCCESS; +} + +TEE_Result tee_mac_init( + void *ctx, uint32_t algo, const uint8_t *key, size_t len) +{ + TEE_Result res; + int ltc_hashindex, ltc_cipherindex; + uint8_t iv[CBCMAC_MAX_BLOCK_LEN]; + struct cbc_state *cbc; + + switch (algo) { + case TEE_ALG_HMAC_MD5: + case TEE_ALG_HMAC_SHA224: + case TEE_ALG_HMAC_SHA1: + case TEE_ALG_HMAC_SHA256: + case TEE_ALG_HMAC_SHA384: + case TEE_ALG_HMAC_SHA512: + res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); + if (res != TEE_SUCCESS) + return res; + if (CRYPT_OK != + hmac_init((hmac_state *)ctx, ltc_hashindex, key, len)) + return TEE_ERROR_BAD_STATE; + break; + + case TEE_ALG_AES_CBC_MAC_NOPAD: + case TEE_ALG_AES_CBC_MAC_PKCS5: + case TEE_ALG_DES_CBC_MAC_NOPAD: + case TEE_ALG_DES_CBC_MAC_PKCS5: + case TEE_ALG_DES3_CBC_MAC_NOPAD: + case TEE_ALG_DES3_CBC_MAC_PKCS5: + cbc = (struct cbc_state *)ctx; + + res = tee_algo_to_ltc_cipherindex(algo, <c_cipherindex); + if (res != TEE_SUCCESS) + return res; + + cbc->block_len = + cipher_descriptor[ltc_cipherindex].block_length; + if (CBCMAC_MAX_BLOCK_LEN < cbc->block_len) + return TEE_ERROR_BAD_PARAMETERS; + memset(iv, 0, cbc->block_len); + + if (CRYPT_OK != cbc_start( + ltc_cipherindex, iv, key, len, 0, &cbc->cbc)) + return TEE_ERROR_BAD_STATE; + cbc->is_computed = 0; + cbc->current_block_len = 0; + break; + + case TEE_ALG_AES_CMAC: + res = tee_algo_to_ltc_cipherindex(algo, <c_cipherindex); + if (res != TEE_SUCCESS) + return res; + if (CRYPT_OK != omac_init((omac_state *)ctx, ltc_cipherindex, + key, len)) + return TEE_ERROR_BAD_STATE; + break; + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + return TEE_SUCCESS; +} + +TEE_Result tee_mac_update( + void *ctx, uint32_t algo, const uint8_t *data, size_t len) +{ + int ltc_res; + struct cbc_state *cbc; + size_t pad_len; + + switch (algo) { + case TEE_ALG_HMAC_MD5: + case TEE_ALG_HMAC_SHA224: + case TEE_ALG_HMAC_SHA1: + case TEE_ALG_HMAC_SHA256: + case TEE_ALG_HMAC_SHA384: + case TEE_ALG_HMAC_SHA512: + if (CRYPT_OK != hmac_process((hmac_state *)ctx, data, len)) + return TEE_ERROR_BAD_STATE; + break; + + case TEE_ALG_AES_CBC_MAC_NOPAD: + case TEE_ALG_AES_CBC_MAC_PKCS5: + case TEE_ALG_DES_CBC_MAC_NOPAD: + case TEE_ALG_DES_CBC_MAC_PKCS5: + case TEE_ALG_DES3_CBC_MAC_NOPAD: + case TEE_ALG_DES3_CBC_MAC_PKCS5: + cbc = (struct cbc_state *)ctx; + + if ((cbc->current_block_len > 0) && + (len + cbc->current_block_len >= cbc->block_len)) { + pad_len = cbc->block_len - cbc->current_block_len; + memcpy(cbc->block + cbc->current_block_len, + data, pad_len); + data += pad_len; + len -= pad_len; + ltc_res = cbc_encrypt(cbc->block, cbc->digest, + cbc->block_len, &cbc->cbc); + if (CRYPT_OK != ltc_res) + return TEE_ERROR_BAD_STATE; + cbc->is_computed = 1; + } + + while (len >= cbc->block_len) { + ltc_res = cbc_encrypt(data, cbc->digest, + cbc->block_len, &cbc->cbc); + if (CRYPT_OK != ltc_res) + return TEE_ERROR_BAD_STATE; + cbc->is_computed = 1; + data += cbc->block_len; + len -= cbc->block_len; + } + + if (len > 0) + memcpy(cbc->block, data, len); + cbc->current_block_len = len; + break; + + case TEE_ALG_AES_CMAC: + if (CRYPT_OK != omac_process((omac_state *)ctx, data, len)) + return TEE_ERROR_BAD_STATE; + break; + + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + return TEE_SUCCESS; +} + +TEE_Result tee_mac_final( + void *ctx, uint32_t algo, + const uint8_t *data, size_t data_len, + uint8_t *digest, size_t digest_len) +{ + struct cbc_state *cbc; + size_t pad_len; + + switch (algo) { + case TEE_ALG_HMAC_MD5: + case TEE_ALG_HMAC_SHA224: + case TEE_ALG_HMAC_SHA1: + case TEE_ALG_HMAC_SHA256: + case TEE_ALG_HMAC_SHA384: + case TEE_ALG_HMAC_SHA512: + if (CRYPT_OK != hmac_process((hmac_state *)ctx, data, data_len)) + return TEE_ERROR_BAD_STATE; + + if (CRYPT_OK != hmac_done((hmac_state *)ctx, digest, + (unsigned long *)&digest_len)) + return TEE_ERROR_BAD_STATE; + break; + + case TEE_ALG_AES_CBC_MAC_NOPAD: + case TEE_ALG_AES_CBC_MAC_PKCS5: + case TEE_ALG_DES_CBC_MAC_NOPAD: + case TEE_ALG_DES_CBC_MAC_PKCS5: + case TEE_ALG_DES3_CBC_MAC_NOPAD: + case TEE_ALG_DES3_CBC_MAC_PKCS5: + cbc = (struct cbc_state *)ctx; + + if (TEE_SUCCESS != tee_mac_update(ctx, algo, data, data_len)) + return TEE_ERROR_BAD_STATE; + + /* Padding is required */ + switch (algo) { + case TEE_ALG_AES_CBC_MAC_PKCS5: + case TEE_ALG_DES_CBC_MAC_PKCS5: + case TEE_ALG_DES3_CBC_MAC_PKCS5: + /* + * Padding is in whole bytes. The value of each added + * byte is the number of bytes that are added, i.e. N + * bytes, each of value N are added + */ + pad_len = cbc->block_len - cbc->current_block_len; + memset(cbc->block+cbc->current_block_len, + pad_len, pad_len); + cbc->current_block_len = 0; + if (TEE_SUCCESS != tee_mac_update( + ctx, algo, cbc->block, cbc->block_len)) + return TEE_ERROR_BAD_STATE; + break; + default: + /* nothing to do */ + break; + } + + if ((!cbc->is_computed) || (cbc->current_block_len != 0)) + return TEE_ERROR_BAD_STATE; + + memcpy(digest, cbc->digest, MIN(digest_len, cbc->block_len)); + tee_cipher_final(&cbc->cbc, algo); + break; + + case TEE_ALG_AES_CMAC: + if (CRYPT_OK != omac_process((omac_state *)ctx, data, data_len)) + return TEE_ERROR_BAD_STATE; + if (CRYPT_OK != omac_done((omac_state *)ctx, digest, + (unsigned long *)&digest_len)) + return TEE_ERROR_BAD_STATE; + break; + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + return TEE_SUCCESS; +} diff --git a/core/tee/tee_obj.c b/core/tee/tee_obj.c new file mode 100644 index 00000000000..7a381ca7521 --- /dev/null +++ b/core/tee/tee_obj.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#include +#include + +void tee_obj_add(struct tee_ta_ctx *ctx, struct tee_obj *o) +{ + TAILQ_INSERT_TAIL(&ctx->objects, o, link); +} + +TEE_Result tee_obj_get(struct tee_ta_ctx *ctx, uint32_t obj_id, + struct tee_obj **obj) +{ + struct tee_obj *o; + + TAILQ_FOREACH(o, &ctx->objects, link) { + if (obj_id == (uint32_t) o) { + *obj = o; + return TEE_SUCCESS; + } + } + return TEE_ERROR_BAD_PARAMETERS; +} + +void tee_obj_close(struct tee_ta_ctx *ctx, struct tee_obj *o) +{ + TAILQ_REMOVE(&ctx->objects, o, link); + + if ((o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) && o->fd) { + tee_fs_close(o->fd); + tee_pobj_release(o->pobj); + } + + free(o->data); + free(o); +} + +void tee_obj_close_all(struct tee_ta_ctx *ctx) +{ + struct tee_obj_head *objects = &ctx->objects; + + while (!TAILQ_EMPTY(objects)) + tee_obj_close(ctx, TAILQ_FIRST(objects)); +} diff --git a/core/tee/tee_pobj.c b/core/tee/tee_pobj.c new file mode 100644 index 00000000000..972405fbfc1 --- /dev/null +++ b/core/tee/tee_pobj.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include + +static TAILQ_HEAD(tee_pobjs, tee_pobj) tee_pobjs = +TAILQ_HEAD_INITIALIZER(tee_pobjs); + +static TEE_Result tee_pobj_check_access(uint32_t oflags, uint32_t nflags) +{ + /* meta is exclusive */ + if (oflags | TEE_DATA_FLAG_ACCESS_WRITE_META || + nflags | TEE_DATA_FLAG_ACCESS_WRITE_META) + return TEE_ERROR_ACCESS_CONFLICT; + + if (oflags | TEE_DATA_FLAG_ACCESS_READ && + !((nflags | TEE_DATA_FLAG_SHARE_READ) && + oflags | TEE_DATA_FLAG_SHARE_READ)) + return TEE_ERROR_ACCESS_CONFLICT; + + if (oflags | TEE_DATA_FLAG_ACCESS_WRITE && + !((nflags | TEE_DATA_FLAG_SHARE_WRITE) && + oflags | TEE_DATA_FLAG_SHARE_WRITE)) + return TEE_ERROR_ACCESS_CONFLICT; + + return TEE_SUCCESS; +} + +TEE_Result tee_pobj_get(TEE_UUID *uuid, void *obj_id, uint32_t obj_id_len, + uint32_t flags, struct tee_pobj **obj) +{ + struct tee_pobj *o; + TEE_Result res; + + *obj = NULL; + + /* Check if file is open */ + TAILQ_FOREACH(o, &tee_pobjs, link) { + if ((obj_id_len == o->obj_id_len) && + (memcmp(obj_id, o->obj_id, obj_id_len) == 0) && + (memcmp(uuid, &o->uuid, sizeof(TEE_UUID)) == 0)) { + *obj = o; + } + } + + if (*obj) { + res = tee_pobj_check_access((*obj)->flags, flags); + if (res != TEE_SUCCESS) { + *obj = NULL; + return res; + } + + (*obj)->refcnt++; + return TEE_SUCCESS; + } + + /* new file */ + o = calloc(sizeof(struct tee_pobj), 1); + + if (o == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + o->refcnt = 1; + memcpy(&o->uuid, uuid, sizeof(TEE_UUID)); + o->flags = flags; + + o->obj_id = malloc(obj_id_len); + if (o->obj_id == NULL) { + free(o); + return TEE_ERROR_OUT_OF_MEMORY; + } + memcpy(o->obj_id, obj_id, obj_id_len); + o->obj_id_len = obj_id_len; + + TAILQ_INSERT_TAIL(&tee_pobjs, o, link); + *obj = o; + + return TEE_SUCCESS; +} + +TEE_Result tee_pobj_release(struct tee_pobj *obj) +{ + if (obj == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + obj->refcnt--; + if (obj->refcnt == 0) { + TAILQ_REMOVE(&tee_pobjs, obj, link); + free(obj->obj_id); + free(obj); + } + + return TEE_SUCCESS; +} + +TEE_Result tee_pobj_rename(struct tee_pobj *obj, void *obj_id, + uint32_t obj_id_len) +{ + TEE_Result res = TEE_SUCCESS; + void *new_obj_id = NULL; + + if (obj == NULL || obj_id == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + if (obj->refcnt != 1) + return TEE_ERROR_BAD_STATE; + + new_obj_id = malloc(obj_id_len); + if (new_obj_id == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto exit; + } + memcpy(new_obj_id, obj_id, obj_id_len); + + /* update internal data */ + free(obj->obj_id); + obj->obj_id = new_obj_id; + obj->obj_id_len = obj_id_len; + new_obj_id = NULL; + +exit: + free(new_obj_id); + return res; +} + +void tee_pobj_init(void) +{ + TAILQ_INIT(&tee_pobjs); +} diff --git a/core/tee/tee_rpmb.c b/core/tee/tee_rpmb.c new file mode 100644 index 00000000000..9a87e70439e --- /dev/null +++ b/core/tee/tee_rpmb.c @@ -0,0 +1,1216 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RPMB_DATA_OFFSET (RPMB_STUFF_DATA_SIZE + RPMB_KEY_MAC_SIZE) +#define RPMB_MAC_PROTECT_DATA_SIZE (RPMB_DATA_FRAME_SIZE - RPMB_DATA_OFFSET) + +#define RPMB_MSG_TYPE_REQ_AUTH_KEY_PROGRAM 0x0001 +#define RPMB_MSG_TYPE_REQ_WRITE_COUNTER_VAL_READ 0x0002 +#define RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE 0x0003 +#define RPMB_MSG_TYPE_REQ_AUTH_DATA_READ 0x0004 +#define RPMB_MSG_TYPE_REQ_RESULT_READ 0x0005 +#define RPMB_MSG_TYPE_RESP_AUTH_KEY_PROGRAM 0x0100 +#define RPMB_MSG_TYPE_RESP_WRITE_COUNTER_VAL_READ 0x0200 +#define RPMB_MSG_TYPE_RESP_AUTH_DATA_WRITE 0x0300 +#define RPMB_MSG_TYPE_RESP_AUTH_DATA_READ 0x0400 + +#define RPMB_STUFF_DATA_SIZE 196 +#define RPMB_KEY_MAC_SIZE 32 +#define RPMB_DATA_SIZE 256 +#define RPMB_NONCE_SIZE 16 +#define RPMB_DATA_FRAME_SIZE 512 + +#define RPMB_RESULT_OK 0x00 +#define RPMB_RESULT_GENERAL_FAILURE 0x01 +#define RPMB_RESULT_AUTH_FAILURE 0x02 +#define RPMB_RESULT_COUNTER_FAILURE 0x03 +#define RPMB_RESULT_ADDRESS_FAILURE 0x04 +#define RPMB_RESULT_WRITE_FAILURE 0x05 +#define RPMB_RESULT_READ_FAILURE 0x06 +#define RPMB_RESULT_AUTH_KEY_NOT_PROGRAMMED 0x07 +#define RPMB_RESULT_MASK 0x3F +#define RPMB_RESULT_WR_CNT_EXPIRED 0x80 + +/* RPMB internal commands */ +#define RPMB_CMD_DATA_REQ 0x00 +#define RPMB_CMD_GET_DEV_INFO 0x01 + +#define RPMB_SIZE_SINGLE (128 * 1024) + +/* Error codes for get_dev_info request/response. */ +#define RPMB_CMD_GET_DEV_INFO_RET_OK 0x00 +#define RPMB_CMD_GET_DEV_INFO_RET_ERROR 0x01 + +struct rpmb_data_frame { + uint8_t stuff_bytes[RPMB_STUFF_DATA_SIZE]; + uint8_t key_mac[RPMB_KEY_MAC_SIZE]; + uint8_t data[RPMB_DATA_SIZE]; + uint8_t nonce[RPMB_NONCE_SIZE]; + uint8_t write_counter[4]; + uint8_t address[2]; + uint8_t block_count[2]; + uint8_t op_result[2]; + uint8_t msg_type[2]; +}; + +struct rpmb_req { + uint16_t cmd; + uint16_t dev_id; + /* variable length of data */ + /* uint8_t data[]; REMOVED! */ +}; + +#define TEE_RPMB_REQ_DATA(req) \ + ((void *)((struct rpmb_req *)(req) + 1)) + +struct rpmb_raw_data { + uint16_t msg_type; + uint16_t *op_result; + uint16_t *block_count; + uint16_t *blk_idx; + uint32_t *write_counter; + uint8_t *nonce; + uint8_t *key_mac; + uint8_t *data; + /* data length to read or write */ + uint32_t len; + /* Byte address offset in the first block involved */ + uint8_t byte_offset; +}; + +#define RPMB_EMMC_CID_SIZE 16 +struct rpmb_dev_info { + uint8_t cid[RPMB_EMMC_CID_SIZE]; + /* EXT CSD-slice 168 "RPMB Size" */ + uint8_t rpmb_size_mult; + /* EXT CSD-slice 222 "Reliable Write Sector Count" */ + uint8_t rel_wr_sec_c; + /* Check the ret code and accept the data only if it is OK. */ + uint8_t ret_code; +}; + +/* + * Struct for rpmb context data. + * + * @key RPMB key. + * @cid eMMC card ID. + * @hash_ctx_size Hash context size + * @wr_cnt Current write counter. + * @max_blk_idx The highest block index supported by current device. + * @rel_wr_blkcnt Max number of data blocks for each reliable write. + * @dev_id Device ID of the eMMC device. + * @wr_cnt_synced Flag indicating if write counter is synced to RPMB. + * @key_derived Flag indicating if key has been generated. + * @key_verified Flag indicating the key generated is verified ok. + * @dev_info_synced Flag indicating if dev info has been retrieved from RPMB. + */ +struct tee_rpmb_ctx { + uint8_t key[RPMB_KEY_MAC_SIZE]; + uint8_t cid[RPMB_EMMC_CID_SIZE]; + uint32_t hash_ctx_size; + uint32_t wr_cnt; + uint16_t max_blk_idx; + uint16_t rel_wr_blkcnt; + uint16_t dev_id; + bool wr_cnt_synced; + bool key_derived; + bool key_verified; + bool dev_info_synced; +}; + +static struct tee_rpmb_ctx *rpmb_ctx; + +static TEE_Result mac_calc(uint8_t *mac, uint32_t macsize, + uint8_t *data, uint32_t datasize, + uint8_t *key, uint32_t keylen) +{ + return tee_hash_createdigest( + TEE_ALG_HMAC_SHA256, data, datasize, mac, macsize); +} + +static TEE_Result mac_init(void *ctx, const uint8_t *key, uint32_t keysize) +{ + return tee_hash_init(ctx, TEE_ALG_HMAC_SHA256); +} + +static TEE_Result mac_update(void *ctx, const uint8_t *data, uint32_t datasize) +{ + return tee_hash_update(ctx, TEE_ALG_HMAC_SHA256, data, datasize); +} + +static TEE_Result mac_final(void *ctx, uint8_t *mac, uint32_t macsize) +{ + return tee_hash_final(ctx, TEE_ALG_HMAC_SHA256, mac, macsize); +} + +/* + * NOTE: We need a common API to get hw unique key and it + * should return error when the hw unique is not a valid + * one as stated below. + * We need to make sure the hw unique we get is valid by: + * 1. In case of HUK is used, checking if OTP is hidden (in + * which case only zeros will be returned) or not; + * 2. In case of SSK is used, checking if SSK in OTP is + * write_locked (which means a valid key is provisioned) + * or not. + * + * Maybe tee_get_hw_unique_key() should be exposed as + * generic API for getting hw unique key! + * We should change the API tee_otp_get_hw_unique_key() + * to return error code! + */ +static TEE_Result tee_get_hw_unique_key(struct tee_hw_unique_key *hwkey) +{ + if (NULL == hwkey) + return TEE_ERROR_BAD_PARAMETERS; + + tee_otp_get_hw_unique_key(hwkey); + + return TEE_SUCCESS; +} + +static TEE_Result tee_rpmb_key_gen(uint16_t dev_id, + uint8_t *key, uint32_t len, bool commercial) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct tee_hw_unique_key hwkey; + + if (key == NULL || RPMB_KEY_MAC_SIZE != len) + return TEE_ERROR_BAD_PARAMETERS; + + if (commercial) { + res = tee_get_hw_unique_key(&hwkey); + if (res != TEE_SUCCESS) + return res; + } else { + memset(&hwkey, 0x00, HW_UNIQUE_KEY_LENGTH); + } + + res = mac_calc((uint8_t *)key, len, + (uint8_t *)rpmb_ctx->cid, + RPMB_EMMC_CID_SIZE, + (uint8_t *)&hwkey, HW_UNIQUE_KEY_LENGTH); + if (res != TEE_SUCCESS) + return res; + + return TEE_SUCCESS; +} + +static void u32_to_bytes(uint32_t u32, uint8_t *bytes) +{ + *bytes = (uint8_t) (u32 >> 24); + *(bytes + 1) = (uint8_t) (u32 >> 16); + *(bytes + 2) = (uint8_t) (u32 >> 8); + *(bytes + 3) = (uint8_t) u32; +} + +static void bytes_to_u32(uint8_t *bytes, uint32_t *u32) +{ + *u32 = (uint32_t) ((*(bytes) << 24) + + (*(bytes + 1) << 16) + + (*(bytes + 2) << 8) + (*(bytes + 3))); +} + +static void u16_to_bytes(uint16_t u16, uint8_t *bytes) +{ + *bytes = (uint8_t) (u16 >> 8); + *(bytes + 1) = (uint8_t) u16; +} + +static void bytes_to_u16(uint8_t *bytes, uint16_t *u16) +{ + *u16 = (uint16_t) ((*bytes << 8) + *(bytes + 1)); +} + +static TEE_Result tee_rpmb_mac_calc(uint8_t *mac, uint32_t macsize, + uint8_t *key, uint32_t keysize, + struct rpmb_data_frame *datafrms, + uint16_t blkcnt) +{ + TEE_Result res = TEE_ERROR_GENERIC; + int i; + uint8_t *ctx = NULL; + + if (mac == NULL || key == NULL || datafrms == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + ctx = malloc(rpmb_ctx->hash_ctx_size); + if (ctx == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + res = mac_init(ctx, key, keysize); + if (res != TEE_SUCCESS) + goto func_exit; + + for (i = 0; i < blkcnt; i++) { + res = + mac_update(ctx, datafrms[i].data, + RPMB_MAC_PROTECT_DATA_SIZE); + if (res != TEE_SUCCESS) + goto func_exit; + } + + res = mac_final(ctx, mac, macsize); + if (res != TEE_SUCCESS) + goto func_exit; + + res = TEE_SUCCESS; + +func_exit: + free(ctx); + return res; +} + +struct tee_rpmb_mem { + struct teesmc32_arg *arg; + paddr_t pharg; + paddr_t phpayload; + paddr_t phreq; + paddr_t phresp; + size_t req_size; + size_t resp_size; +}; + +static void tee_rpmb_free(struct tee_rpmb_mem *mem) +{ + if (!mem) + return; + thread_rpc_free_arg(mem->pharg); + thread_rpc_free_payload(mem->phpayload); + mem->pharg = 0; + mem->phpayload = 0; +} + + +static TEE_Result tee_rpmb_alloc(size_t req_size, size_t resp_size, + struct tee_rpmb_mem *mem, void **req, void **resp) +{ + TEE_Result res = TEE_SUCCESS; + size_t req_s = TEE_ROUNDUP(req_size, sizeof(uint32_t)); + size_t resp_s = TEE_ROUNDUP(resp_size, sizeof(uint32_t)); + + if (!mem) + return TEE_ERROR_BAD_PARAMETERS; + + mem->pharg = 0; + mem->phpayload = 0; + + mem->pharg = thread_rpc_alloc_arg(TEESMC32_GET_ARG_SIZE(2)); + mem->phpayload = thread_rpc_alloc_payload(req_s + resp_s); + if (!mem->pharg || !mem->phpayload) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + mem->phreq = mem->phpayload; + mem->phresp = mem->phpayload + req_s; + + if (core_pa2va(mem->pharg, (uint32_t *)&mem->arg) || + core_pa2va(mem->phreq, (uint32_t *)req) || + core_pa2va(mem->phresp, (uint32_t *)resp)) { + res = TEE_ERROR_GENERIC; + goto out; + } + + mem->req_size = req_size; + mem->resp_size = resp_size; + +out: + if (res != TEE_SUCCESS) + tee_rpmb_free(mem); + return res; +} + +static TEE_Result tee_rpmb_invoke(struct tee_rpmb_mem *mem) +{ + struct teesmc32_param *params; + + memset(mem->arg, 0, TEESMC32_GET_ARG_SIZE(2)); + + mem->arg->cmd = TEE_RPC_RPMB_CMD; + /* In case normal world doesn't update anything */ + mem->arg->ret = TEE_ERROR_GENERIC; + + mem->arg->num_params = 2; + params = TEESMC32_GET_PARAMS(mem->arg); + params[0].attr = TEESMC_ATTR_TYPE_MEMREF_INPUT | + (TEESMC_ATTR_CACHE_I_WRITE_THR | + TEESMC_ATTR_CACHE_O_WRITE_THR) << + TEESMC_ATTR_CACHE_SHIFT; + params[1].attr = TEESMC_ATTR_TYPE_MEMREF_OUTPUT | + (TEESMC_ATTR_CACHE_I_WRITE_THR | + TEESMC_ATTR_CACHE_O_WRITE_THR) << + TEESMC_ATTR_CACHE_SHIFT; + + params[0].u.memref.buf_ptr = mem->phreq; + params[0].u.memref.size = mem->req_size; + params[1].u.memref.buf_ptr = mem->phresp; + params[1].u.memref.size = mem->resp_size; + + thread_rpc_cmd(mem->pharg); + return mem->arg->ret; +} + + +static TEE_Result tee_rpmb_req_pack(struct rpmb_req *req, + struct rpmb_raw_data *rawdata, + uint16_t nbr_frms, uint16_t dev_id) +{ + TEE_Result res = TEE_ERROR_GENERIC; + int i; + int j; + struct rpmb_data_frame *datafrm; + + if (req == NULL || rawdata == NULL || nbr_frms == 0) + return TEE_ERROR_BAD_PARAMETERS; + + /* + * Check write blockcount is not bigger than reliable write + * blockcount. + */ + if ((rawdata->msg_type == RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE) && + (nbr_frms > rpmb_ctx->rel_wr_blkcnt)) { + DMSG("%s: wr_blkcnt(%d) > rel_wr_blkcnt(%d)", __func__, + nbr_frms, rpmb_ctx->rel_wr_blkcnt); + return TEE_ERROR_GENERIC; + } + + req->cmd = RPMB_CMD_DATA_REQ; + req->dev_id = dev_id; + + /* Allocate memory for construct all data packets and calculate MAC. */ + datafrm = calloc(nbr_frms, RPMB_DATA_FRAME_SIZE); + if (datafrm == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + for (i = 0; i < nbr_frms; i++) { + u16_to_bytes(rawdata->msg_type, datafrm[i].msg_type); + + if (rawdata->block_count != NULL) + u16_to_bytes(*rawdata->block_count, + datafrm[i].block_count); + + if (rawdata->blk_idx != NULL) { + /* Check the block index is within range. */ + if ((*rawdata->blk_idx + nbr_frms) > + rpmb_ctx->max_blk_idx) { + DMSG("%s: blk_idx (%d+%d) > max_blk_idx(%d)", + __func__, *rawdata->blk_idx, nbr_frms, + rpmb_ctx->max_blk_idx); + res = TEE_ERROR_GENERIC; + goto func_exit; + } + u16_to_bytes(*rawdata->blk_idx, datafrm[i].address); + } + + if (rawdata->write_counter != NULL) + u32_to_bytes(*rawdata->write_counter, + datafrm[i].write_counter); + + if (rawdata->nonce != NULL) + memcpy(datafrm[i].nonce, rawdata->nonce, + RPMB_NONCE_SIZE); + + if (rawdata->data != NULL) + for (j = 0; j < nbr_frms; j++) + memcpy((datafrm + j)->data, + rawdata->data + RPMB_DATA_SIZE * j, + RPMB_DATA_SIZE); + } + + if (rawdata->key_mac != NULL) { + if (rawdata->msg_type == RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE) { + res = + tee_rpmb_mac_calc(rawdata->key_mac, + RPMB_KEY_MAC_SIZE, rpmb_ctx->key, + RPMB_KEY_MAC_SIZE, datafrm, + nbr_frms); + if (res != TEE_SUCCESS) + goto func_exit; + } + memcpy(datafrm[nbr_frms - 1].key_mac, + rawdata->key_mac, RPMB_KEY_MAC_SIZE); + } + + memcpy(TEE_RPMB_REQ_DATA(req), datafrm, + nbr_frms * RPMB_DATA_FRAME_SIZE); + +#ifdef ENABLE_RPMB_DATA_DUMP + for (i = 0; i < nbr_frms; i++) { + DMSG("%s: Dumping datafrm[%d]:", __func__, i); + HEX_PRINT_BUF((uint8_t *)&datafrm[i] + RPMB_STUFF_DATA_SIZE, + 512 - RPMB_STUFF_DATA_SIZE); + } +#endif + + res = TEE_SUCCESS; +func_exit: + free(datafrm); + return res; +} + +static TEE_Result tee_rpmb_data_cpy_mac_calc(struct rpmb_data_frame *datafrm, + struct rpmb_raw_data *rawdata, + uint16_t nbr_frms, + struct rpmb_data_frame *lastfrm) +{ + TEE_Result res = TEE_ERROR_GENERIC; + int i; + uint8_t *ctx = NULL; + uint16_t offset; + uint32_t size1; + uint32_t size2; + uint8_t *data; + + if (datafrm == NULL || rawdata == NULL || + nbr_frms == 0 || lastfrm == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + data = rawdata->data; + + if (nbr_frms == 1) { + res = mac_calc(rawdata->key_mac, RPMB_KEY_MAC_SIZE, + lastfrm->data, RPMB_MAC_PROTECT_DATA_SIZE, + rpmb_ctx->key, RPMB_KEY_MAC_SIZE); + if (res != TEE_SUCCESS) + return res; + + memcpy(data, lastfrm->data + rawdata->byte_offset, + rawdata->len); + return TEE_SUCCESS; + } + + ctx = malloc(rpmb_ctx->hash_ctx_size); + if (ctx == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + res = mac_init(ctx, rpmb_ctx->key, RPMB_KEY_MAC_SIZE); + if (res != TEE_SUCCESS) + goto func_exit; + + for (i = 0; i < (nbr_frms - 1); i++) { + offset = RPMB_DATA_OFFSET; + size1 = 0; + size2 = 0; + + if (i == 0) { + /* Handling the first block */ + if (rawdata->byte_offset != 0) { + size1 = rawdata->byte_offset; + + res = + mac_update(ctx, + (uint8_t *)datafrm + offset, + size1); + if (res != TEE_SUCCESS) + goto func_exit; + + offset += size1; + } + size2 = RPMB_DATA_SIZE - rawdata->byte_offset; + } else { + /* Handling the middle blocks */ + size2 = RPMB_DATA_SIZE; + } + + /* Copy the data part for each block. */ + memcpy(data, (uint8_t *)&datafrm[i] + offset, size2); + + /* Calculate HMAC against the data copied. */ + res = mac_update(ctx, (uint8_t *)data, size2); + if (res != TEE_SUCCESS) + goto func_exit; + + data += size2; + offset += size2; + + res = mac_update(ctx, (uint8_t *)&datafrm[i] + offset, + RPMB_MAC_PROTECT_DATA_SIZE - (size1 + size2)); + if (res != TEE_SUCCESS) + goto func_exit; + } + + /* Copy the data part for the last block. */ + size2 = (rawdata->len + rawdata->byte_offset) % RPMB_DATA_SIZE; + if (size2 == 0) + size2 = RPMB_DATA_SIZE; + + memcpy(data, lastfrm->data, size2); + + /* Update MAC against the last block */ + res = mac_update(ctx, lastfrm->data, RPMB_MAC_PROTECT_DATA_SIZE); + if (res != TEE_SUCCESS) + goto func_exit; + + res = mac_final(ctx, rawdata->key_mac, RPMB_KEY_MAC_SIZE); + if (res != TEE_SUCCESS) + goto func_exit; + + res = TEE_SUCCESS; + +func_exit: + free(ctx); + return res; +} + +static TEE_Result tee_rpmb_resp_unpack_verify(struct rpmb_data_frame *datafrm, + struct rpmb_raw_data *rawdata, + uint16_t nbr_frms) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint16_t msg_type; + uint32_t wr_cnt; + uint16_t blk_idx; + uint16_t op_result; + struct rpmb_data_frame lastfrm; + + if (datafrm == NULL || rawdata == NULL || nbr_frms == 0) + return TEE_ERROR_BAD_PARAMETERS; + +#ifdef ENABLE_RPMB_DATA_DUMP + uint32_t i = 0; + for (i = 0; i < nbr_frms; i++) { + DMSG("%s: Dumping datafrm[%d]:", __func__, i); + HEX_PRINT_BUF((uint8_t *)&datafrm[i] + RPMB_STUFF_DATA_SIZE, + 512 - RPMB_STUFF_DATA_SIZE); + } +#endif + + /* Make a secure copy of the last data packet for verification. */ + memcpy(&lastfrm, &datafrm[nbr_frms - 1], RPMB_DATA_FRAME_SIZE); + + /* Handle operation result and translate to TEEC error code. */ + bytes_to_u16(lastfrm.op_result, &op_result); + if (rawdata->op_result != NULL) + *rawdata->op_result = op_result; + if (op_result != RPMB_RESULT_OK) { + DMSG("%s: op_result != RPMB_RESULT_OK", __func__); + return TEE_ERROR_GENERIC; + } + + /* Check the response msg_type. */ + bytes_to_u16(lastfrm.msg_type, &msg_type); + if (msg_type != rawdata->msg_type) { + DMSG("%s: Unexpected msg_type", __func__); + return TEE_ERROR_GENERIC; + } + + if (rawdata->blk_idx != NULL) { + bytes_to_u16(lastfrm.address, &blk_idx); + if (blk_idx != *rawdata->blk_idx) { + DMSG("%s: Unexpected block index", __func__); + return TEE_ERROR_GENERIC; + } + } + + if (rawdata->write_counter != NULL) { + wr_cnt = *rawdata->write_counter; + bytes_to_u32(lastfrm.write_counter, rawdata->write_counter); + if (msg_type == RPMB_MSG_TYPE_RESP_AUTH_DATA_WRITE) { + /* Verify the write counter is incremented by 1 */ + if (*rawdata->write_counter != wr_cnt + 1) { + DMSG("%s: write counter mismatched", __func__); + return TEE_ERROR_SECURITY; + } + rpmb_ctx->wr_cnt++; + } + } + + if (rawdata->nonce != NULL) { + if (memcmp(rawdata->nonce, lastfrm.nonce, RPMB_NONCE_SIZE) + != 0) { + DMSG("%s: nonce mismatched", __func__); + return TEE_ERROR_SECURITY; + } + } + + if (rawdata->key_mac != NULL) { + if (msg_type == RPMB_MSG_TYPE_RESP_AUTH_DATA_READ) { + if (rawdata->data == NULL) + return TEE_ERROR_GENERIC; + + res = tee_rpmb_data_cpy_mac_calc(datafrm, rawdata, + nbr_frms, &lastfrm); + if (res != TEE_SUCCESS) + return res; + } else { + /* + * There should be only one data frame for + * other msg types. + */ + if (nbr_frms != 1) + return TEE_ERROR_GENERIC; + + res = mac_calc(rawdata->key_mac, RPMB_KEY_MAC_SIZE, + lastfrm.data, RPMB_MAC_PROTECT_DATA_SIZE, + rpmb_ctx->key, RPMB_KEY_MAC_SIZE); + if (res != TEE_SUCCESS) + return res; + } + + if (memcmp(rawdata->key_mac, + (datafrm + nbr_frms - 1)->key_mac, + RPMB_KEY_MAC_SIZE) != 0) { + DMSG("%s: MAC mismatched:", __func__); +#ifdef ENABLE_RPMB_DATA_DUMP + HEX_PRINT_BUF((uint8_t *)rawdata->key_mac, 32); +#endif + return TEE_ERROR_SECURITY; + } + } + + return TEE_SUCCESS; +} + +static TEE_Result tee_rpmb_get_dev_info(uint16_t dev_id, + struct rpmb_dev_info *dev_info) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct tee_rpmb_mem mem; + struct rpmb_req *req = NULL; + uint8_t *resp = NULL; + uint32_t req_size; + uint32_t resp_size; + + if (dev_info == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + req_size = sizeof(struct rpmb_req); + resp_size = sizeof(struct rpmb_dev_info); + res = tee_rpmb_alloc(req_size, resp_size, &mem, + (void *)&req, (void *)&resp); + if (res != TEE_SUCCESS) + goto func_exit; + + req->cmd = RPMB_CMD_GET_DEV_INFO; + req->dev_id = dev_id; + + ((struct rpmb_dev_info *)resp)->ret_code = + RPMB_CMD_GET_DEV_INFO_RET_ERROR; + + res = tee_rpmb_invoke(&mem); + if (res != TEE_SUCCESS) + goto func_exit; + + if (((struct rpmb_dev_info *)resp)->ret_code != + RPMB_CMD_GET_DEV_INFO_RET_OK) { + DMSG("RPMB_CMD_GET_DEV_INFO not OK"); + res = TEE_ERROR_GENERIC; + goto func_exit; + } + + memcpy((uint8_t *)dev_info, resp, sizeof(struct rpmb_dev_info)); + +#ifdef ENABLE_RPMB_DATA_DUMP + DMSG("Dumping DEV INFO:"); + HEX_PRINT_BUF((uint8_t *)dev_info, sizeof(struct rpmb_dev_info)); +#endif + + res = TEE_SUCCESS; + +func_exit: + tee_rpmb_free(&mem); + return res; +} + +static TEE_Result tee_rpmb_init_read_wr_cnt(uint16_t dev_id, + uint32_t *wr_cnt, + uint16_t *op_result) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct tee_rpmb_mem mem; + uint16_t msg_type; + uint8_t nonce[RPMB_NONCE_SIZE]; + uint8_t hmac[RPMB_KEY_MAC_SIZE]; + struct rpmb_req *req = NULL; + struct rpmb_data_frame *resp = NULL; + struct rpmb_raw_data rawdata; + uint32_t req_size; + uint32_t resp_size; + + if (wr_cnt == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + req_size = sizeof(struct rpmb_req) + RPMB_DATA_FRAME_SIZE; + resp_size = RPMB_DATA_FRAME_SIZE; + res = tee_rpmb_alloc(req_size, resp_size, &mem, + (void *)&req, (void *)&resp); + if (res != TEE_SUCCESS) + goto func_exit; + + res = get_rng_array(nonce, RPMB_NONCE_SIZE); + if (res != TEE_SUCCESS) + goto func_exit; + + msg_type = RPMB_MSG_TYPE_REQ_WRITE_COUNTER_VAL_READ; + + memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data)); + rawdata.msg_type = msg_type; + rawdata.nonce = nonce; + + res = tee_rpmb_req_pack(req, &rawdata, 1, dev_id); + if (res != TEE_SUCCESS) + goto func_exit; + + res = tee_rpmb_invoke(&mem); + if (res != TEE_SUCCESS) + goto func_exit; + + msg_type = RPMB_MSG_TYPE_RESP_WRITE_COUNTER_VAL_READ; + + memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data)); + rawdata.msg_type = msg_type; + rawdata.op_result = op_result; + rawdata.write_counter = wr_cnt; + rawdata.nonce = nonce; + rawdata.key_mac = hmac; + + res = tee_rpmb_resp_unpack_verify(resp, &rawdata, 1); + if (res != TEE_SUCCESS) + goto func_exit; + + res = TEE_SUCCESS; + +func_exit: + tee_rpmb_free(&mem); + return res; +} + +/* + * This function must never return TEE_SUCCESS if rpmb_ctx == NULL. + */ +static TEE_Result tee_rpmb_init(uint16_t dev_id, bool writekey, bool commercial) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct rpmb_dev_info dev_info; + uint16_t op_result; + + if (rpmb_ctx == NULL) { + rpmb_ctx = calloc(1, sizeof(struct tee_rpmb_ctx)); + if (rpmb_ctx == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + } else if (rpmb_ctx->dev_id != dev_id) { + memset(rpmb_ctx, 0x00, sizeof(struct tee_rpmb_ctx)); + } + + rpmb_ctx->dev_id = dev_id; + + if (!rpmb_ctx->dev_info_synced) { + dev_info.rpmb_size_mult = 0; + res = tee_rpmb_get_dev_info(dev_id, &dev_info); + if (res != TEE_SUCCESS) + goto func_exit; + + if (dev_info.rpmb_size_mult == 0) { + res = TEE_ERROR_GENERIC; + goto func_exit; + } + + rpmb_ctx->max_blk_idx = (dev_info.rpmb_size_mult * + RPMB_SIZE_SINGLE / RPMB_DATA_SIZE) - 1; + + memcpy(rpmb_ctx->cid, dev_info.cid, RPMB_EMMC_CID_SIZE); + + if ((rpmb_ctx->hash_ctx_size == 0) && + (tee_hash_get_ctx_size( + TEE_ALG_HMAC_SHA256, + (size_t *)(&rpmb_ctx->hash_ctx_size)))) { + rpmb_ctx->hash_ctx_size = 0; + res = TEE_ERROR_GENERIC; + goto func_exit; + } + +#ifdef RPMB_DRIVER_MULTIPLE_WRITE_FIXED + rpmb_ctx->rel_wr_blkcnt = dev_info.rel_wr_sec_c * 2; +#else + rpmb_ctx->rel_wr_blkcnt = 1; +#endif + + rpmb_ctx->dev_info_synced = true; + } + + if (!rpmb_ctx->key_derived) { + res = tee_rpmb_key_gen(dev_id, rpmb_ctx->key, + RPMB_KEY_MAC_SIZE, commercial); + if (res != TEE_SUCCESS) + goto func_exit; + + rpmb_ctx->key_derived = true; + } + + /* Perform a write counter read to verify if the key is ok. */ + if (!rpmb_ctx->wr_cnt_synced || !rpmb_ctx->key_verified) { + res = + tee_rpmb_init_read_wr_cnt(dev_id, &rpmb_ctx->wr_cnt, + &op_result); + + if (res == TEE_SUCCESS) { + rpmb_ctx->key_verified = true; + rpmb_ctx->wr_cnt_synced = true; + + if (writekey) { + /* + * Return security error here as we SHOULD NOT + * allow writing key if the key is already + * programmed. This is to prevent leaking the + * key which is carried in write key request in + * plain text and exposed to normal world during + * write key request. + */ + res = TEE_ERROR_SECURITY; + } + } + } + +func_exit: + return res; +} + +TEE_Result tee_rpmb_write_key(uint16_t dev_id, bool commercial) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct tee_rpmb_mem mem; + uint16_t msg_type; + struct rpmb_req *req = NULL; + struct rpmb_data_frame *resp = NULL; + struct rpmb_raw_data rawdata; + uint32_t req_size; + uint32_t resp_size; + + res = tee_rpmb_init(dev_id, true, commercial); + if (res != TEE_SUCCESS) + return res; + + req_size = sizeof(struct rpmb_req) + RPMB_DATA_FRAME_SIZE; + resp_size = RPMB_DATA_FRAME_SIZE; + res = tee_rpmb_alloc(req_size, resp_size, &mem, + (void *)&req, (void *)&resp); + if (res != TEE_SUCCESS) + goto func_exit; + + msg_type = RPMB_MSG_TYPE_REQ_AUTH_KEY_PROGRAM; + + memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data)); + rawdata.msg_type = msg_type; + rawdata.key_mac = rpmb_ctx->key; + + res = tee_rpmb_req_pack(req, &rawdata, 1, dev_id); + if (res != TEE_SUCCESS) + goto func_exit; + + res = tee_rpmb_invoke(&mem); + if (res != TEE_SUCCESS) + goto func_exit; + + msg_type = RPMB_MSG_TYPE_RESP_AUTH_KEY_PROGRAM; + + memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data)); + rawdata.msg_type = msg_type; + + res = tee_rpmb_resp_unpack_verify(resp, &rawdata, 1); + if (res != TEE_SUCCESS) + goto func_exit; + + res = TEE_SUCCESS; + +func_exit: + tee_rpmb_free(&mem); + return res; +} + +TEE_Result tee_rpmb_read(uint16_t dev_id, + uint32_t addr, uint8_t *data, uint32_t len) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct tee_rpmb_mem mem; + uint16_t msg_type; + uint8_t nonce[RPMB_NONCE_SIZE]; + uint8_t hmac[RPMB_KEY_MAC_SIZE]; + struct rpmb_req *req = NULL; + struct rpmb_data_frame *resp = NULL; + struct rpmb_raw_data rawdata; + uint32_t req_size; + uint32_t resp_size; + uint16_t blk_idx; + uint16_t blkcnt; + uint8_t byte_offset; + + if (data == NULL || len == 0) + return TEE_ERROR_BAD_PARAMETERS; + + blk_idx = addr / RPMB_DATA_SIZE; + byte_offset = addr % RPMB_DATA_SIZE; + + blkcnt = + TEE_ROUNDUP(len + byte_offset, RPMB_DATA_SIZE) / RPMB_DATA_SIZE; + + res = tee_rpmb_init(dev_id, false, true); + if (res != TEE_SUCCESS) + return res; + + req_size = sizeof(struct rpmb_req) + RPMB_DATA_FRAME_SIZE; + resp_size = RPMB_DATA_FRAME_SIZE * blkcnt; + res = tee_rpmb_alloc(req_size, resp_size, &mem, + (void *)&req, (void *)&resp); + if (res != TEE_SUCCESS) + goto func_exit; + + msg_type = RPMB_MSG_TYPE_REQ_AUTH_DATA_READ; + res = get_rng_array(nonce, RPMB_NONCE_SIZE); + if (res != TEE_SUCCESS) + goto func_exit; + + memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data)); + rawdata.msg_type = msg_type; + rawdata.nonce = nonce; + rawdata.blk_idx = &blk_idx; + res = tee_rpmb_req_pack(req, &rawdata, 1, dev_id); + if (res != TEE_SUCCESS) + goto func_exit; + + res = tee_rpmb_invoke(&mem); + if (res != TEE_SUCCESS) + goto func_exit; + + msg_type = RPMB_MSG_TYPE_RESP_AUTH_DATA_READ; + + memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data)); + rawdata.msg_type = msg_type; + rawdata.block_count = &blkcnt; + rawdata.blk_idx = &blk_idx; + rawdata.nonce = nonce; + rawdata.key_mac = hmac; + rawdata.data = data; + + rawdata.len = len; + rawdata.byte_offset = byte_offset; + + res = tee_rpmb_resp_unpack_verify(resp, &rawdata, blkcnt); + if (res != TEE_SUCCESS) + goto func_exit; + + res = TEE_SUCCESS; + +func_exit: + tee_rpmb_free(&mem); + return res; +} + +static TEE_Result tee_rpmb_write_blk(uint16_t dev_id, + uint16_t blk_idx, + uint8_t *data_blks, uint16_t blkcnt) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct tee_rpmb_mem mem; + uint16_t msg_type; + uint32_t wr_cnt; + uint8_t hmac[RPMB_KEY_MAC_SIZE]; + struct rpmb_req *req = NULL; + struct rpmb_data_frame *resp = NULL; + struct rpmb_raw_data rawdata; + uint32_t req_size; + uint32_t resp_size; + uint32_t nbr_writes; + uint16_t tmp_blkcnt; + uint16_t tmp_blk_idx; + uint16_t i; + + if (data_blks == NULL || blkcnt == 0) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_rpmb_init(dev_id, false, true); + if (res != TEE_SUCCESS) + return res; + + /* + * We need to split data when block count + * is bigger than reliable block write count. + */ + if (blkcnt < rpmb_ctx->rel_wr_blkcnt) + req_size = sizeof(struct rpmb_req) + + RPMB_DATA_FRAME_SIZE * blkcnt; + else + req_size = sizeof(struct rpmb_req) + + RPMB_DATA_FRAME_SIZE * rpmb_ctx->rel_wr_blkcnt; + + resp_size = RPMB_DATA_FRAME_SIZE; + res = tee_rpmb_alloc(req_size, resp_size, &mem, + (void *)&req, (void *)&resp); + if (res != TEE_SUCCESS) + goto func_exit; + + nbr_writes = blkcnt / rpmb_ctx->rel_wr_blkcnt; + if (blkcnt % rpmb_ctx->rel_wr_blkcnt > 0) + nbr_writes += 1; + + tmp_blkcnt = rpmb_ctx->rel_wr_blkcnt; + tmp_blk_idx = blk_idx; + for (i = 0; i < nbr_writes; i++) { + /* + * To handle the last write of block count which is + * equal or smaller than reliable write block count. + */ + if (i == nbr_writes - 1) + tmp_blkcnt = blkcnt - rpmb_ctx->rel_wr_blkcnt * + (nbr_writes - 1); + + msg_type = RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE; + wr_cnt = rpmb_ctx->wr_cnt; + + memset(req, 0x00, req_size); + memset(resp, 0x00, resp_size); + + memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data)); + rawdata.msg_type = msg_type; + rawdata.block_count = &tmp_blkcnt; + rawdata.blk_idx = &tmp_blk_idx; + rawdata.write_counter = &wr_cnt; + rawdata.key_mac = hmac; + rawdata.data = data_blks + i * rpmb_ctx->rel_wr_blkcnt * + RPMB_DATA_SIZE; + + res = tee_rpmb_req_pack(req, &rawdata, tmp_blkcnt, dev_id); + if (res != TEE_SUCCESS) + goto func_exit; + + res = tee_rpmb_invoke(&mem); + if (res != TEE_SUCCESS) { + /* + * To force wr_cnt sync next time, as it might get + * out of sync due to inconsistent operation result! + */ + rpmb_ctx->wr_cnt_synced = false; + goto func_exit; + } + + msg_type = RPMB_MSG_TYPE_RESP_AUTH_DATA_WRITE; + + memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data)); + rawdata.msg_type = msg_type; + rawdata.block_count = &tmp_blkcnt; + rawdata.blk_idx = &tmp_blk_idx; + rawdata.write_counter = &wr_cnt; + rawdata.key_mac = hmac; + + res = tee_rpmb_resp_unpack_verify(resp, &rawdata, 1); + if (res != TEE_SUCCESS) { + /* + * To force wr_cnt sync next time, as it might get + * out of sync due to inconsistent operation result! + */ + rpmb_ctx->wr_cnt_synced = false; + goto func_exit; + } + + tmp_blk_idx += tmp_blkcnt; + } + + res = TEE_SUCCESS; + +func_exit: + tee_rpmb_free(&mem); + return res; +} + +TEE_Result tee_rpmb_write(uint16_t dev_id, + uint32_t addr, uint8_t *data, uint32_t len) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t *data_tmp = NULL; + uint16_t blk_idx; + uint16_t blkcnt; + uint8_t byte_offset; + + blk_idx = addr / RPMB_DATA_SIZE; + byte_offset = addr % RPMB_DATA_SIZE; + + blkcnt = + TEE_ROUNDUP(len + byte_offset, RPMB_DATA_SIZE) / RPMB_DATA_SIZE; + + if (byte_offset == 0 && (len % RPMB_DATA_SIZE) == 0) { + res = tee_rpmb_write_blk(dev_id, blk_idx, data, blkcnt); + if (res != TEE_SUCCESS) + goto func_exit; + } else { + data_tmp = calloc(blkcnt, RPMB_DATA_SIZE); + if (data_tmp == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + /* Read the complete blocks */ + res = tee_rpmb_read(dev_id, blk_idx * RPMB_DATA_SIZE, + data_tmp, blkcnt * RPMB_DATA_SIZE); + if (res != TEE_SUCCESS) + goto func_exit; + + /* Partial update of the data blocks */ + memcpy(data_tmp + byte_offset, data, len); + + res = tee_rpmb_write_blk(dev_id, blk_idx, data_tmp, blkcnt); + if (res != TEE_SUCCESS) + goto func_exit; + } + + res = TEE_SUCCESS; + +func_exit: + free(data_tmp); + return res; +} + +TEE_Result tee_rpmb_get_write_counter(uint16_t dev_id, uint32_t *counter) +{ + TEE_Result res; + + if (counter == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + if (rpmb_ctx == NULL || !rpmb_ctx->wr_cnt_synced) { + res = tee_rpmb_init(dev_id, false, true); + if (res != TEE_SUCCESS) + return res; + } + + *counter = rpmb_ctx->wr_cnt; + + return TEE_SUCCESS; +} diff --git a/core/tee/tee_rpmb_fs.c b/core/tee/tee_rpmb_fs.c new file mode 100644 index 00000000000..1b4f7e76020 --- /dev/null +++ b/core/tee/tee_rpmb_fs.c @@ -0,0 +1,598 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +#define RPMB_STORAGE_START_ADDRESS 0 +#define RPMB_FS_FAT_START_ADDRESS 512 +#define RPMB_STORAGE_END_ADDRESS ((1024 * 128) - 1) +#define RPMB_BLOCK_SIZE_SHIFT 8 + +#define DEV_ID 0 +#define RPMB_FS_MAGIC 0x52504D42 +#define FS_VERSION 1 +#define N_ENTRIES 16 + +#define FILE_IS_ACTIVE (1u << 0) +#define FILE_IS_LAST_ENTRY (1u << 1) + +/** + * FS parameters: Information often used by internal functions. + * fat_start_address will be set by rpmb_fs_setup(). + * rpmb_fs_parameters can be read by any other function. + */ +struct rpmb_fs_parameters { + uint32_t fat_start_address; +}; + +/** + * File entry for a single file in a RPMB_FS partition. + */ +struct rpmb_fat_entry { + uint32_t start_address; + uint32_t data_size; + uint32_t flags; + uint32_t write_counter; + char filename[FILENAME_LENGTH]; +}; + +/** + * FAT entry context with reference to a FAT entry and its + * location in RPMB. + */ +struct file_handle { + /* Pointer to a fat_entry */ + struct rpmb_fat_entry fat_entry; + /* Pointer to a filename */ + const char *filename; + /* Adress for current entry in RPMB */ + uint32_t rpmb_fat_address; +}; + +/** + * RPMB_FS partition data + */ +struct rpmb_fs_partition { + uint32_t rpmb_fs_magic; + uint32_t fs_version; + uint32_t write_counter; + uint32_t fat_start_address; + /* Do not use reserved[] for other purpose than partition data. */ + uint8_t reserved[112]; +}; + +static struct rpmb_fs_parameters *fs_par; + +static struct file_handle *alloc_file_handle(const char *filename) +{ + struct file_handle *fh = NULL; + + fh = calloc(1, sizeof(struct file_handle)); + if (fh == NULL) + return NULL; + + if (filename != NULL) + fh->filename = filename; + + return fh; +} + +/** + * write_fat_entry: Store info in a fat_entry to RPMB. + */ +static TEE_Result write_fat_entry(struct file_handle *fh, + bool update_write_counter) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + /* Protect partition data. */ + if (fh->rpmb_fat_address < sizeof(struct rpmb_fs_partition)) { + res = TEE_ERROR_ACCESS_CONFLICT; + goto out; + } + + if (fh->rpmb_fat_address % sizeof(struct rpmb_fat_entry) != 0) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if (update_write_counter) { + res = tee_rpmb_get_write_counter(DEV_ID, + &fh->fat_entry.write_counter); + if (res != TEE_SUCCESS) + goto out; + } + + res = tee_rpmb_write(DEV_ID, fh->rpmb_fat_address, + (uint8_t *)&fh->fat_entry, + sizeof(struct rpmb_fat_entry)); + +out: + return res; +} + +/** + * rpmb_fs_setup: Setup rpmb fs. + * Set initial partition and FS values and write to RPMB. + * Store frequently used data in RAM. + */ +static TEE_Result rpmb_fs_setup(void) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct rpmb_fs_partition *partition_data = NULL; + struct file_handle *fh = NULL; + + partition_data = calloc(1, sizeof(struct rpmb_fs_partition)); + if (partition_data == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = tee_rpmb_read(DEV_ID, RPMB_STORAGE_START_ADDRESS, + (uint8_t *)partition_data, + sizeof(struct rpmb_fs_partition)); + if (res != TEE_SUCCESS) + goto out; + + if (partition_data->rpmb_fs_magic == RPMB_FS_MAGIC) { + if (partition_data->fs_version == FS_VERSION) { + res = TEE_SUCCESS; + goto store_fs_par; + } else { + /* Wrong software is in use. */ + res = TEE_ERROR_ACCESS_DENIED; + goto out; + } + } + + /* Setup new partition data. */ + partition_data->rpmb_fs_magic = RPMB_FS_MAGIC; + partition_data->fs_version = FS_VERSION; + partition_data->fat_start_address = RPMB_FS_FAT_START_ADDRESS; + + /* Initial FAT entry with FILE_IS_LAST_ENTRY flag set. */ + fh = alloc_file_handle(NULL); + if (fh == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + fh->fat_entry.flags = FILE_IS_LAST_ENTRY; + fh->rpmb_fat_address = partition_data->fat_start_address; + + /* Write init FAT entry and partition data to RPMB. */ + res = write_fat_entry(fh, true); + if (res != TEE_SUCCESS) + goto out; + + res = + tee_rpmb_get_write_counter(DEV_ID, &partition_data->write_counter); + if (res != TEE_SUCCESS) + goto out; + res = tee_rpmb_write(DEV_ID, RPMB_STORAGE_START_ADDRESS, + (uint8_t *)partition_data, + sizeof(struct rpmb_fs_partition)); + +store_fs_par: + /* Store FAT start address. */ + if (fs_par == NULL) { + fs_par = calloc(1, sizeof(struct rpmb_fs_parameters)); + if (fs_par == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + } + + fs_par->fat_start_address = partition_data->fat_start_address; + +out: + free(fh); + free(partition_data); + + return res; +} + +/** + * get_fat_start_address: + * FAT start_address from fs_par. + */ +static TEE_Result get_fat_start_address(uint32_t *addr) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + if (fs_par == NULL) { + res = rpmb_fs_setup(); + if (res != TEE_SUCCESS) + goto out; + } + + *addr = fs_par->fat_start_address; + res = TEE_SUCCESS; + +out: + return res; +} + +/** + * read_fat: Read FAT entries + * Return matching FAT entry for read, rm rename and stat. + * Build up memory pool and return matching entry for write operation. + * "Last FAT entry" can be returned during write. + */ +static TEE_Result read_fat(struct file_handle *fh, tee_mm_pool_t *p) +{ + TEE_Result res = TEE_ERROR_GENERIC; + tee_mm_entry_t *mm = NULL; + struct rpmb_fat_entry *fat_entries = NULL; + uint32_t fat_address; + size_t size; + int i; + bool entry_found = false; + bool last_entry_found = false; + + res = rpmb_fs_setup(); + if (res != TEE_SUCCESS) + goto out; + + res = get_fat_start_address(&fat_address); + if (res != TEE_SUCCESS) + goto out; + + size = N_ENTRIES * sizeof(struct rpmb_fat_entry); + fat_entries = malloc(size); + if (fat_entries == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + while (!last_entry_found && !entry_found) { + res = tee_rpmb_read(DEV_ID, fat_address, + (uint8_t *)fat_entries, size); + if (res != TEE_SUCCESS) + goto out; + + for (i = 0; i < N_ENTRIES; i++) { + /* + * Look for an entry, matching filenames. (read, rm, + * rename and stat.). Only store first filename match. + */ + if ((fh->filename != NULL) && + (strcmp(fh->filename, + fat_entries[i].filename) == 0) && + (fat_entries[i].flags & FILE_IS_ACTIVE) && + (!entry_found)) { + entry_found = true; + fh->rpmb_fat_address = fat_address; + memcpy(&fh->fat_entry, &fat_entries[i], + sizeof(struct rpmb_fat_entry)); + if (p == NULL) + break; + } + + /* Add existing files to memory pool. (write) */ + if (p != NULL) { + if ((fat_entries[i].flags & FILE_IS_ACTIVE) != + 0) { + mm = tee_mm_alloc2 + (p, + fat_entries[i].start_address, + fat_entries[i].data_size); + if (mm == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + } + + /* Unused FAT entries can be reused (write) */ + if (((fat_entries[i].flags & FILE_IS_ACTIVE) == + 0) && (fh->rpmb_fat_address == 0)) { + fh->rpmb_fat_address = fat_address; + memcpy(&fh->fat_entry, &fat_entries[i], + sizeof(struct rpmb_fat_entry)); + } + } + + if ((fat_entries[i].flags & FILE_IS_LAST_ENTRY) != 0) { + last_entry_found = true; + if (p != NULL && fh->rpmb_fat_address == 0) { + fh->rpmb_fat_address = fat_address; + fh->fat_entry.flags = + FILE_IS_LAST_ENTRY; + } + break; + } + + /* Move to next fat_entry. */ + fat_address += sizeof(struct rpmb_fat_entry); + } + } + + if ((p != NULL) && last_entry_found) { + /* Make room for yet a FAT entry and add to memory pool. */ + fat_address += 2 * sizeof(struct rpmb_fat_entry); + mm = tee_mm_alloc2(p, RPMB_STORAGE_START_ADDRESS, fat_address); + if (mm == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + } + + if (fh->filename != NULL && fh->rpmb_fat_address == 0) + res = TEE_ERROR_FILE_NOT_FOUND; + +out: + free(fat_entries); + return res; +} + +/** + * add_fat_entry: + * Populate last FAT entry. + */ +static TEE_Result add_fat_entry(struct file_handle *fh) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + fh->rpmb_fat_address += sizeof(struct rpmb_fat_entry); + res = write_fat_entry(fh, true); + fh->rpmb_fat_address -= sizeof(struct rpmb_fat_entry); + + return res; +} + +int tee_rpmb_fs_read(const char *filename, uint8_t *buf, size_t size) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct file_handle *fh = NULL; + int read_size = -1; + + if (filename == NULL || buf == NULL || + strlen(filename) >= FILENAME_LENGTH - 1) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + fh = alloc_file_handle(filename); + if (fh == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = read_fat(fh, NULL); + if (res != TEE_SUCCESS) + goto out; + + if (size < fh->fat_entry.data_size) { + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + res = tee_rpmb_read(DEV_ID, fh->fat_entry.start_address, buf, + fh->fat_entry.data_size); + +out: + if (res == TEE_SUCCESS) + read_size = fh->fat_entry.data_size; + + free(fh); + + return read_size; +} + +int tee_rpmb_fs_write(const char *filename, uint8_t *buf, size_t size) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct file_handle *fh = NULL; + tee_mm_pool_t p; + tee_mm_entry_t *mm = NULL; + size_t length; + uint32_t mm_flags; + + if (filename == NULL || buf == NULL) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + length = strlen(filename); + if ((length >= FILENAME_LENGTH - 1) || (length == 0)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + /* Create a FAT entry for the file to write. */ + fh = alloc_file_handle(filename); + if (fh == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + /* Upper memory allocation must be used for RPMB_FS. */ + mm_flags = TEE_MM_POOL_HI_ALLOC; + if (!tee_mm_init + (&p, RPMB_STORAGE_START_ADDRESS, RPMB_STORAGE_END_ADDRESS, + RPMB_BLOCK_SIZE_SHIFT, mm_flags)) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = read_fat(fh, &p); + if (res != TEE_SUCCESS) + goto out; + + mm = tee_mm_alloc(&p, size); + if (mm == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + if ((fh->fat_entry.flags & FILE_IS_LAST_ENTRY) != 0) { + res = add_fat_entry(fh); + if (res != TEE_SUCCESS) + goto out; + } + + memset(&fh->fat_entry, 0, sizeof(struct rpmb_fat_entry)); + memcpy(fh->fat_entry.filename, filename, length); + fh->fat_entry.data_size = size; + fh->fat_entry.flags = FILE_IS_ACTIVE; + fh->fat_entry.start_address = tee_mm_get_smem(mm); + + res = tee_rpmb_write(DEV_ID, fh->fat_entry.start_address, buf, size); + if (res != TEE_SUCCESS) + goto out; + + res = write_fat_entry(fh, true); + +out: + free(fh); + if (mm != NULL) + tee_mm_final(&p); + + if (res == TEE_SUCCESS) + return size; + + return -1; +} + +TEE_Result tee_rpmb_fs_rm(const char *filename) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct file_handle *fh = NULL; + + if (filename == NULL || strlen(filename) >= FILENAME_LENGTH - 1) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + fh = alloc_file_handle(filename); + if (fh == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = read_fat(fh, NULL); + if (res != TEE_SUCCESS) + goto out; + + /* Clear this file entry. */ + memset(&fh->fat_entry, 0, sizeof(struct rpmb_fat_entry)); + res = write_fat_entry(fh, false); + +out: + free(fh); + + return res; +} + +TEE_Result tee_rpmb_fs_rename(const char *old_name, const char *new_name) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct file_handle *fh_old = NULL; + struct file_handle *fh_new = NULL; + uint32_t old_len; + uint32_t new_len; + + if (old_name == NULL || new_name == NULL) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + old_len = strlen(old_name); + new_len = strlen(new_name); + + if ((old_len >= FILENAME_LENGTH - 1) || + (new_len >= FILENAME_LENGTH - 1) || (new_len == 0)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + fh_old = alloc_file_handle(old_name); + if (fh_old == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + fh_new = alloc_file_handle(new_name); + if (fh_new == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = read_fat(fh_old, NULL); + if (res != TEE_SUCCESS) + goto out; + + res = read_fat(fh_new, NULL); + if (res == TEE_SUCCESS) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + memset(fh_old->fat_entry.filename, 0, FILENAME_LENGTH); + memcpy(fh_old->fat_entry.filename, new_name, new_len); + + res = write_fat_entry(fh_old, false); + +out: + free(fh_old); + free(fh_new); + + return res; +} + +TEE_Result tee_rpmb_fs_stat(const char *filename, + struct tee_rpmb_fs_stat *stat) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct file_handle *fh = NULL; + + if (stat == NULL || filename == NULL) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + fh = alloc_file_handle(filename); + if (fh == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = read_fat(fh, NULL); + if (res != TEE_SUCCESS) + goto out; + + stat->size = fh->fat_entry.data_size; + stat->reserved = 0; + +out: + free(fh); + return res; +} diff --git a/core/tee/tee_svc.c b/core/tee/tee_svc.c new file mode 100644 index 00000000000..41fc0678907 --- /dev/null +++ b/core/tee/tee_svc.c @@ -0,0 +1,875 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +void tee_svc_sys_log(const void *buf, size_t len) +{ + char *kbuf; + + if (len == 0) + return; + + kbuf = malloc(len); + if (kbuf == NULL) + return; + + /* log as Info/Raw traces */ + if (tee_svc_copy_from_user(NULL, kbuf, buf, len) == TEE_SUCCESS) + ATAMSG_RAW("%s", kbuf); + + free(kbuf); +} + +void tee_svc_sys_panic(uint32_t code) +{ + struct tee_ta_session *sess; + + if (tee_ta_get_current_session(&sess) == TEE_SUCCESS) { + EMSG("Set session 0x%x to panicked", sess); + sess->ctx->panicked = 1; + sess->ctx->panic_code = code; + + { + /* + * Force panicking. This memory error will be trapped by + * the error exception handler myErrorHandler() + */ + EMSG("Following 'DTLB exception in bundle'"); + EMSG(" is generated with code %d", code); + int *p = 0; + *p = 1; + } + } else { + DMSG("Panic called from unknown TA"); + } +} + +uint32_t tee_svc_sys_dummy(uint32_t *a) +{ + DMSG("tee_svc_sys_dummy: a 0x%x", (unsigned int)a); + return 0; +} + +uint32_t tee_svc_sys_dummy_7args(uint32_t a1, uint32_t a2, uint32_t a3, + uint32_t a4, uint32_t a5, uint32_t a6, + uint32_t a7) +{ + DMSG("tee_svc_sys_dummy_7args: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, %x, %x\n", + a1, a2, a3, a4, a5, a6, a7); + return 0; +} + +uint32_t tee_svc_sys_nocall(void) +{ + DMSG("No syscall"); + return 0x1; +} + +TEE_Result tee_svc_sys_get_property(uint32_t prop, tee_uaddr_t buf, size_t blen) +{ + static const char api_vers[] = "1.0"; + static const char descr[] = "Version N.N"; + /* + * Value 100 means: + * System time based on REE-controlled timers. Can be tampered by the + * REE. The implementation must still guarantee that the system time + * is monotonous, i.e., successive calls to TEE_GetSystemTime must + * return increasing values of the system time. + */ + static const uint32_t sys_time_prot_lvl = 100; + static const uint32_t ta_time_prot_lvl = 100; + struct tee_ta_session *sess; + TEE_Result res; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + switch (prop) { + case UTEE_PROP_TEE_API_VERSION: + if (blen < sizeof(api_vers)) + return TEE_ERROR_SHORT_BUFFER; + return tee_svc_copy_to_user(sess, (void *)buf, api_vers, + sizeof(api_vers)); + + case UTEE_PROP_TEE_DESCR: + if (blen < sizeof(descr)) + return TEE_ERROR_SHORT_BUFFER; + return tee_svc_copy_to_user(sess, (void *)buf, descr, + sizeof(descr)); + + case UTEE_PROP_TEE_DEV_ID: + { + TEE_UUID uuid; + const size_t nslen = 4; + uint8_t data[4 + + FVR_DIE_ID_NUM_REGS * sizeof(uint32_t)] = { + 'S', 'T', 'E', 'E' }; + + if (blen < sizeof(uuid)) + return TEE_ERROR_SHORT_BUFFER; + + if (tee_otp_get_die_id + (data + nslen, sizeof(data) - nslen)) + return TEE_ERROR_BAD_STATE; + + res = tee_hash_createdigest( + TEE_ALG_SHA256, + data, sizeof(data), + (uint8_t *)&uuid, sizeof(uuid)); + if (res != TEE_SUCCESS) + return TEE_ERROR_BAD_STATE; + + /* + * Changes the random value into and UUID as specifiec + * in RFC 4122. The magic values are from the example + * code in the RFC. + * + * TEE_UUID is defined slightly different from the RFC, + * but close enough for our purpose. + */ + + uuid.timeHiAndVersion &= 0x0fff; + uuid.timeHiAndVersion |= 5 << 12; + + /* uuid.clock_seq_hi_and_reserved in the RFC */ + uuid.clockSeqAndNode[0] &= 0x3f; + uuid.clockSeqAndNode[0] |= 0x80; + + return tee_svc_copy_to_user(sess, (void *)buf, &uuid, + sizeof(TEE_UUID)); + } + + case UTEE_PROP_TEE_SYS_TIME_PROT_LEVEL: + if (blen < sizeof(sys_time_prot_lvl)) + return TEE_ERROR_SHORT_BUFFER; + return tee_svc_copy_to_user(sess, (void *)buf, + &sys_time_prot_lvl, + sizeof(sys_time_prot_lvl)); + + case UTEE_PROP_TEE_TA_TIME_PROT_LEVEL: + if (blen < sizeof(ta_time_prot_lvl)) + return TEE_ERROR_SHORT_BUFFER; + return tee_svc_copy_to_user(sess, (void *)buf, + &ta_time_prot_lvl, + sizeof(ta_time_prot_lvl)); + + case UTEE_PROP_TEE_ARITH_MAX_BIG_INT_SIZE: + { + uint32_t v = LTC_MAX_BITS_PER_VARIABLE / 2; + + if (blen < sizeof(v)) + return TEE_ERROR_SHORT_BUFFER; + + return tee_svc_copy_to_user(sess, (void *)buf, &v, + sizeof(v)); + } + + case UTEE_PROP_CLIENT_ID: + { + if (blen < sizeof(TEE_Identity)) + return TEE_ERROR_SHORT_BUFFER; + + return tee_svc_copy_to_user(sess, (void *)buf, + &sess->clnt_id, + sizeof(TEE_Identity)); + } + case UTEE_PROP_TA_APP_ID: + { + if (blen < sizeof(TEE_UUID)) + return TEE_ERROR_SHORT_BUFFER; + + return tee_svc_copy_to_user(sess, (void *)buf, + &sess->ctx->head->uuid, + sizeof(TEE_UUID)); + } + + default: + break; + } + return TEE_ERROR_NOT_IMPLEMENTED; +} + +/* + * TA invokes some TA with parameter. + * If some parameters are memory references: + * - either the memref is inside TA private RAM: TA is not allowed to expose + * its private RAM: use a temporary memory buffer and copy the data. + * - or the memref is not in the TA private RAM: + * - if the memref was mapped to the TA, TA is allowed to expose it. + * - if so, converts memref virtual address into a physical address. + */ +static TEE_Result tee_svc_copy_param(struct tee_ta_session *sess, + struct tee_ta_session *called_sess, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS], + struct tee_ta_param *param, + tee_paddr_t tmp_buf_pa[TEE_NUM_PARAMS], + tee_mm_entry_t **mm) +{ + size_t n; + TEE_Result res; + size_t req_mem = 0; + size_t s; + uint8_t *dst = 0; + tee_paddr_t dst_pa, src_pa = 0; + bool ta_private_memref[TEE_NUM_PARAMS]; + + param->types = param_types; + if (params == NULL) { + if (param->types != 0) + return TEE_ERROR_BAD_PARAMETERS; + memset(param->params, 0, sizeof(param->params)); + } else { + tee_svc_copy_from_user(sess, param->params, params, + sizeof(param->params)); + } + + if ((called_sess != NULL) && + (called_sess->ctx->static_ta == NULL) && + (called_sess->ctx->flags & TA_FLAG_USER_MODE) == 0) { + /* + * kernel TA, borrow the mapping of the calling + * during this call. + */ + called_sess->calling_sess = sess; + return TEE_SUCCESS; + } + + for (n = 0; n < TEE_NUM_PARAMS; n++) { + + ta_private_memref[n] = false; + + switch (TEE_PARAM_TYPE_GET(param->types, n)) { + case TEE_PARAM_TYPE_MEMREF_INPUT: + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + if (param->params[n].memref.buffer == NULL) { + if (param->params[n].memref.size != 0) + return TEE_ERROR_BAD_PARAMETERS; + break; + } + /* uTA cannot expose its private memory */ + if (tee_mmu_is_vbuf_inside_ta_private(sess->ctx, + (uintptr_t)param->params[n].memref.buffer, + param->params[n].memref.size)) { + + s = TEE_ROUNDUP(param->params[n].memref.size, + sizeof(uint32_t)); + /* Check overflow */ + if (req_mem + s < req_mem) + return TEE_ERROR_BAD_PARAMETERS; + req_mem += s; + ta_private_memref[n] = true; + break; + } + if (!tee_mmu_is_vbuf_outside_ta_private(sess->ctx, + (uintptr_t)param->params[n].memref.buffer, + param->params[n].memref.size)) + return TEE_ERROR_BAD_PARAMETERS; + + if (tee_mmu_user_va2pa(sess->ctx, + (void *)param->params[n].memref.buffer, + (void **)&src_pa) != TEE_SUCCESS) + return TEE_ERROR_BAD_PARAMETERS; + + param->param_attr[n] = tee_mmu_user_get_cache_attr( + sess->ctx, + (void *)param->params[n].memref.buffer); + + param->params[n].memref.buffer = (void *)src_pa; + break; + + default: + break; + } + } + + if (req_mem == 0) + return TEE_SUCCESS; + + /* Allocate section in secure DDR */ + *mm = tee_mm_alloc(&tee_mm_sec_ddr, req_mem); + if (*mm == NULL) { + DMSG("tee_mm_alloc TEE_ERROR_GENERIC"); + return TEE_ERROR_GENERIC; + } + + /* Get the virtual address for the section in secure DDR */ + res = tee_mmu_kmap(tee_mm_get_smem(*mm), req_mem, &dst); + if (res != TEE_SUCCESS) + return res; + dst_pa = tee_mm_get_smem(*mm); + + for (n = 0; n < 4; n++) { + + if (ta_private_memref[n] == false) + continue; + + s = TEE_ROUNDUP(param->params[n].memref.size, sizeof(uint32_t)); + + switch (TEE_PARAM_TYPE_GET(param->types, n)) { + case TEE_PARAM_TYPE_MEMREF_INPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + if (param->params[n].memref.buffer != NULL) { + res = tee_svc_copy_from_user(sess, dst, + param->params[n]. + memref.buffer, + param->params[n]. + memref.size); + if (res != TEE_SUCCESS) + return res; + + param->param_attr[n] = + tee_mmu_kmap_get_cache_attr(dst); + param->params[n].memref.buffer = (void *)dst_pa; + tmp_buf_pa[n] = dst_pa; + dst += s; + dst_pa += s; + } + break; + + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + if (param->params[n].memref.buffer != NULL) { + param->param_attr[n] = + tee_mmu_kmap_get_cache_attr(dst); + param->params[n].memref.buffer = (void *)dst_pa; + tmp_buf_pa[n] = dst_pa; + dst += s; + dst_pa += s; + } + break; + + default: + continue; + } + } + + tee_mmu_kunmap(dst, req_mem); + + return TEE_SUCCESS; +} + +/* + * Back from execution of service: update parameters passed from TA: + * If some parameters were memory references: + * - either the memref was temporary: copy back data and update size + * - or it was the original TA memref: update only the size value. + */ +static TEE_Result tee_svc_update_out_param( + struct tee_ta_session *sess, + struct tee_ta_session *called_sess, + struct tee_ta_param *param, + tee_paddr_t tmp_buf_pa[TEE_NUM_PARAMS], + TEE_Param params[TEE_NUM_PARAMS]) +{ + size_t n; + bool have_private_mem_map = (called_sess == NULL) || + (called_sess->ctx->static_ta != NULL) || + ((called_sess->ctx->flags & TA_FLAG_USER_MODE) != 0); + + tee_ta_set_current_session(sess); + + for (n = 0; n < TEE_NUM_PARAMS; n++) { + switch (TEE_PARAM_TYPE_GET(param->types, n)) { + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + + /* outside TA private => memref is valid, update size */ + if (!tee_mmu_is_vbuf_inside_ta_private(sess->ctx, + (uintptr_t)params[n].memref.buffer, + param->params[n].memref.size)) { + params[n].memref.size = + param->params[n].memref.size; + break; + } + + /* + * If we called a kernel TA the parameters are in shared + * memory and no copy is needed. + */ + if (have_private_mem_map && + param->params[n].memref.size <= + params[n].memref.size) { + uint8_t *src = 0; + TEE_Result res; + + /* FIXME: TA_RAM is already mapped ! */ + res = tee_mmu_kmap(tmp_buf_pa[n], + param->params[n].memref.size, &src); + if (res != TEE_SUCCESS) + return TEE_ERROR_GENERIC; + + res = tee_svc_copy_to_user(sess, + params[n].memref. + buffer, src, + param->params[n]. + memref.size); + if (res != TEE_SUCCESS) + return res; + tee_mmu_kunmap(src, + param->params[n].memref.size); + + } + params[n].memref.size = param->params[n].memref.size; + break; + + case TEE_PARAM_TYPE_VALUE_OUTPUT: + case TEE_PARAM_TYPE_VALUE_INOUT: + params[n].value = param->params[n].value; + break; + + default: + continue; + } + } + + return TEE_SUCCESS; +} + +/* Called when a TA calls an OpenSession on another TA */ +TEE_Result tee_svc_open_ta_session(const TEE_UUID *dest, + uint32_t cancel_req_to, uint32_t param_types, + TEE_Param params[4], + TEE_TASessionHandle *ta_sess, + uint32_t *ret_orig) +{ + TEE_Result res; + uint32_t ret_o = TEE_ORIGIN_TEE; + struct tee_ta_session *s = NULL; + struct tee_ta_session *sess; + tee_mm_entry_t *mm_param = NULL; + + TEE_UUID *uuid = malloc(sizeof(TEE_UUID)); + struct tee_ta_param *param = malloc(sizeof(struct tee_ta_param)); + TEE_Identity *clnt_id = malloc(sizeof(TEE_Identity)); + tee_paddr_t tmp_buf_pa[TEE_NUM_PARAMS]; + + if (uuid == NULL || param == NULL || clnt_id == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out_free_only; + } + + memset(param, 0, sizeof(struct tee_ta_param)); + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + goto out_free_only; + + res = tee_svc_copy_from_user(sess, uuid, dest, sizeof(TEE_UUID)); + if (res != TEE_SUCCESS) + goto function_exit; + + clnt_id->login = TEE_LOGIN_TRUSTED_APP; + memcpy(&clnt_id->uuid, &sess->ctx->head->uuid, sizeof(TEE_UUID)); + + res = tee_svc_copy_param(sess, NULL, param_types, params, param, + tmp_buf_pa, &mm_param); + if (res != TEE_SUCCESS) + goto function_exit; + + /* + * Find session of a multi session TA or a static TA + * In such a case, there is no need to ask the supplicant for the TA + * code + */ + res = tee_ta_open_session(&ret_o, &s, &sess->ctx->open_sessions, uuid, + NULL, clnt_id, cancel_req_to, param); + + if (ret_o != TEE_ORIGIN_TEE || res != TEE_ERROR_ITEM_NOT_FOUND) + goto function_exit; + + if (ret_o == TEE_ORIGIN_TEE && res == TEE_ERROR_ITEM_NOT_FOUND) { + kta_signed_header_t *ta = NULL; + struct tee_ta_nwumap lp; + + tee_mmu_set_ctx(NULL); + + /* Load TA */ + res = tee_ta_rpc_load(uuid, &ta, &lp, &ret_o); + if (res != TEE_SUCCESS) { + tee_mmu_set_ctx(sess->ctx); + goto function_exit; + } + + res = tee_ta_open_session(&ret_o, &s, &sess->ctx->open_sessions, + uuid, ta, clnt_id, cancel_req_to, + param); + tee_mmu_set_ctx(sess->ctx); + if (res != TEE_SUCCESS) + goto function_exit; + + s->ctx->nwumap = lp; + } + + res = tee_svc_update_out_param(sess, NULL, param, tmp_buf_pa, params); + if (res != TEE_SUCCESS) + goto function_exit; + +function_exit: + tee_ta_set_current_session(sess); + + if (mm_param != NULL) { + TEE_Result res2; + void *va = 0; + + res2 = + tee_mmu_kmap_pa2va((void *)tee_mm_get_smem(mm_param), &va); + if (res2 == TEE_SUCCESS) + tee_mmu_kunmap(va, tee_mm_get_bytes(mm_param)); + } + tee_mm_free(mm_param); + tee_svc_copy_to_user(sess, ta_sess, &s, sizeof(s)); + tee_svc_copy_to_user(sess, ret_orig, &ret_o, sizeof(ret_o)); + +out_free_only: + free(param); + free(uuid); + free(clnt_id); + return res; +} + +TEE_Result tee_svc_close_ta_session(TEE_TASessionHandle ta_sess) +{ + TEE_Result res; + struct tee_ta_session *sess; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + tee_ta_set_current_session(NULL); + + res = + tee_ta_close_session((uint32_t)ta_sess, &sess->ctx->open_sessions); + tee_ta_set_current_session(sess); + return res; +} + +TEE_Result tee_svc_invoke_ta_command(TEE_TASessionHandle ta_sess, + uint32_t cancel_req_to, uint32_t cmd_id, + uint32_t param_types, TEE_Param params[4], + uint32_t *ret_orig) +{ + TEE_Result res; + uint32_t ret_o = TEE_ORIGIN_TEE; + struct tee_ta_param param = { 0 }; + TEE_Identity clnt_id; + struct tee_ta_session *sess; + struct tee_ta_session *called_sess = (struct tee_ta_session *)ta_sess; + tee_mm_entry_t *mm_param = NULL; + tee_paddr_t tmp_buf_pa[TEE_NUM_PARAMS]; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = + tee_ta_verify_session_pointer(called_sess, + &sess->ctx->open_sessions); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_copy_param(sess, called_sess, param_types, params, + ¶m, tmp_buf_pa, &mm_param); + if (res != TEE_SUCCESS) + goto function_exit; + + res = + tee_ta_invoke_command(&ret_o, called_sess, &clnt_id, cancel_req_to, + cmd_id, ¶m); + if (res != TEE_SUCCESS) + goto function_exit; + + res = tee_svc_update_out_param(sess, called_sess, ¶m, tmp_buf_pa, + params); + if (res != TEE_SUCCESS) + goto function_exit; + +function_exit: + tee_ta_set_current_session(sess); + called_sess->calling_sess = NULL; /* clear eventual borrowed mapping */ + + if (mm_param != NULL) { + TEE_Result res2; + void *va = 0; + + res2 = + tee_mmu_kmap_pa2va((void *)tee_mm_get_smem(mm_param), &va); + if (res2 == TEE_SUCCESS) + tee_mmu_kunmap(va, tee_mm_get_bytes(mm_param)); + } + tee_mm_free(mm_param); + if (ret_orig) + tee_svc_copy_to_user(sess, ret_orig, &ret_o, sizeof(ret_o)); + return res; +} + +TEE_Result tee_svc_check_access_rights(uint32_t flags, const void *buf, + size_t len) +{ + TEE_Result res; + struct tee_ta_session *s; + + res = tee_ta_get_current_session(&s); + if (res != TEE_SUCCESS) + return res; + + return tee_mmu_check_access_rights(s->ctx, flags, (tee_uaddr_t)buf, + len); +} + +TEE_Result tee_svc_copy_from_user(struct tee_ta_session *sess, void *kaddr, + const void *uaddr, size_t len) +{ + TEE_Result res; + struct tee_ta_session *s; + + if (sess == NULL) { + res = tee_ta_get_current_session(&s); + if (res != TEE_SUCCESS) + return res; + } else { + s = sess; + tee_ta_set_current_session(s); + } + res = + tee_mmu_check_access_rights(s->ctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t)uaddr, len); + if (res != TEE_SUCCESS) + return res; + + memcpy(kaddr, uaddr, len); + return TEE_SUCCESS; +} + +TEE_Result tee_svc_copy_to_user(struct tee_ta_session *sess, void *uaddr, + const void *kaddr, size_t len) +{ + TEE_Result res; + struct tee_ta_session *s; + + if (sess == NULL) { + res = tee_ta_get_current_session(&s); + if (res != TEE_SUCCESS) + return res; + } else { + s = sess; + tee_ta_set_current_session(s); + } + + res = + tee_mmu_check_access_rights(s->ctx, + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t)uaddr, len); + if (res != TEE_SUCCESS) + return res; + + memcpy(uaddr, kaddr, len); + return TEE_SUCCESS; +} + +static bool session_is_cancelled(struct tee_ta_session *s, TEE_Time *curr_time) +{ + TEE_Time current_time; + + if (s->cancel_mask) + return false; + + if (s->cancel) + return true; + + if (s->cancel_time.seconds == UINT32_MAX) + return false; + + if (curr_time != NULL) + current_time = *curr_time; + else if (tee_time_get_sys_time(¤t_time) != TEE_SUCCESS) + return false; + + if (current_time.seconds > s->cancel_time.seconds || + (current_time.seconds == s->cancel_time.seconds && + current_time.millis >= s->cancel_time.millis)) { + return true; + } + + return false; +} + +TEE_Result tee_svc_get_cancellation_flag(bool *cancel) +{ + TEE_Result res; + struct tee_ta_session *s = NULL; + bool c; + + res = tee_ta_get_current_session(&s); + if (res != TEE_SUCCESS) + return res; + + c = session_is_cancelled(s, NULL); + + return tee_svc_copy_to_user(s, cancel, &c, sizeof(c)); +} + +TEE_Result tee_svc_unmask_cancellation(bool *old_mask) +{ + TEE_Result res; + struct tee_ta_session *s = NULL; + bool m; + + res = tee_ta_get_current_session(&s); + if (res != TEE_SUCCESS) + return res; + + m = s->cancel_mask; + s->cancel_mask = false; + return tee_svc_copy_to_user(s, old_mask, &m, sizeof(m)); +} + +TEE_Result tee_svc_mask_cancellation(bool *old_mask) +{ + TEE_Result res; + struct tee_ta_session *s = NULL; + bool m; + + res = tee_ta_get_current_session(&s); + if (res != TEE_SUCCESS) + return res; + + m = s->cancel_mask; + s->cancel_mask = true; + return tee_svc_copy_to_user(s, old_mask, &m, sizeof(m)); +} + +TEE_Result tee_svc_wait(uint32_t timeout) +{ + TEE_Result res = TEE_SUCCESS; + uint32_t mytime = 0; + struct tee_ta_session *s; + TEE_Time base_time; + TEE_Time current_time; + + res = tee_ta_get_current_session(&s); + if (res != TEE_SUCCESS) + return res; + + res = tee_time_get_sys_time(&base_time); + if (res != TEE_SUCCESS) + return res; + + while (true) { + res = tee_time_get_sys_time(¤t_time); + if (res != TEE_SUCCESS) + return res; + + if (session_is_cancelled(s, ¤t_time)) + return TEE_ERROR_CANCEL; + + mytime = (current_time.seconds - base_time.seconds) * 1000 + + (int)current_time.millis - (int)base_time.millis; + if (mytime >= timeout) + return TEE_SUCCESS; + + tee_wait_specific(timeout - mytime); + } + + return res; +} + +TEE_Result tee_svc_get_time(enum utee_time_category cat, TEE_Time *mytime) +{ + TEE_Result res, res2; + struct tee_ta_session *s = NULL; + TEE_Time t; + + res = tee_ta_get_current_session(&s); + if (res != TEE_SUCCESS) + return res; + + switch (cat) { + case UTEE_TIME_CAT_SYSTEM: + res = tee_time_get_sys_time(&t); + break; + case UTEE_TIME_CAT_TA_PERSISTENT: + res = + tee_time_get_ta_time((const void *)&s->ctx->head->uuid, &t); + break; + case UTEE_TIME_CAT_REE: + res = tee_time_get_ree_time(&t); + break; + default: + res = TEE_ERROR_BAD_PARAMETERS; + break; + } + + if (res == TEE_SUCCESS || res == TEE_ERROR_OVERFLOW) { + res2 = tee_svc_copy_to_user(s, mytime, &t, sizeof(t)); + if (res2 != TEE_SUCCESS) + res = res2; + } + + return res; +} + +TEE_Result tee_svc_set_ta_time(const TEE_Time *mytime) +{ + TEE_Result res; + struct tee_ta_session *s = NULL; + TEE_Time t; + + res = tee_ta_get_current_session(&s); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_copy_from_user(s, &t, mytime, sizeof(t)); + if (res != TEE_SUCCESS) + return res; + + return tee_time_set_ta_time((const void *)&s->ctx->head->uuid, &t); +} diff --git a/core/tee/tee_svc_cryp.c b/core/tee/tee_svc_cryp.c new file mode 100644 index 00000000000..0fb2bf34521 --- /dev/null +++ b/core/tee/tee_svc_cryp.c @@ -0,0 +1,2711 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Big Numbers, used by LTC, allocation size + */ +#define LTC_BIGNUMBERS_ALLOC_SIZE \ + ((mpa_StaticVarSizeInU32(LTC_MAX_BITS_PER_VARIABLE)) * sizeof(uint32_t)) + +/* + * Set the allocation bytes used for a big number. This is the first uint32_t + * member of the array representing the big number + * Equals the total allocation size + * minus 4 for the 'alloc' member + * minus 4 for the 'size' member + */ +#define SET_MPA_ALLOCSIZE(_x) \ + ((uint32_t *)(_x))[0] = (LTC_BIGNUMBERS_ALLOC_SIZE - 8) + +/* Set an attribute on an object */ +#define SET_ATTRIBUTE(_object, _props, _attr) \ + (_object)->have_attrs |= \ + (1 << (tee_svc_cryp_obj_find_type_attr_idx((_attr), (_props)))) + +/* Get an attribute on an object */ +#define GET_ATTRIBUTE(_object, _props, _attr) \ + ((_object)->have_attrs & \ + (1 << (tee_svc_cryp_obj_find_type_attr_idx((_attr), (_props))))) + +#define TEE_USAGE_DEFAULT 0xffffffff +#define TEE_ATTR_BIT_PROTECTED (1 << 28) + +typedef void (*tee_cryp_ctx_finalize_func_t) (void *ctx, uint32_t algo); +struct tee_cryp_state { + TAILQ_ENTRY(tee_cryp_state) link; + uint32_t algo; + uint32_t mode; + uint32_t key1; + uint32_t key2; + size_t ctx_size; + void *ctx; + tee_cryp_ctx_finalize_func_t ctx_finalize; +}; + +struct tee_cryp_obj_secret { + uint32_t key_size; + + /* + * Pseudo code visualize layout of structure + * Next follows data, such as: + * uint8_t data[key_size] + * key_size must never exceed + * (obj->data_size - sizeof(struct tee_cryp_obj_secret)). + */ +}; + +/* + * Following set of structures contains the "plain" data used by LibTomCrypt + * Translation to the real LTC types (that is only a collection of pointers) + * is then straightforward + */ + +struct ltc_bignumbers { + uint8_t b[LTC_BIGNUMBERS_ALLOC_SIZE]; +}; + +/* + * RSA key pair. Contains the public and private keys. + * rsa_key is the original type from LTC + */ +struct tee_ltc_rsa_key_pair { + struct ltc_bignumbers e; /* the public exponent */ + struct ltc_bignumbers d; /* The private exponent */ + struct ltc_bignumbers N; /* The modulus */ + + /* Next are the CRT parameters, that are optional */ + struct ltc_bignumbers p; /* The p factor of N */ + struct ltc_bignumbers q; /* The q factor of N */ + struct ltc_bignumbers qP; /* The 1/q mod p */ + struct ltc_bignumbers dP; /* The d mod (p - 1) */ + struct ltc_bignumbers dQ; /* The d mod (q - 1) */ +}; + +/* + * RSA public key. rsa_key is the original type from LTC, with type PK_PUBLIC + */ +struct tee_ltc_rsa_public_key { + struct ltc_bignumbers e; /* the public exponent */ + struct ltc_bignumbers N; /* The modulus */ +}; + +/* + * DSA key pair. dsa_key is the original type from LTC, with type PK_PRIVATE + */ +struct tee_ltc_dsa_key_pair { + struct ltc_bignumbers g; /* Base generator */ + struct ltc_bignumbers p; /* Prime modulus */ + struct ltc_bignumbers q; /* Order of subgroup */ + struct ltc_bignumbers y; /* Public key */ + struct ltc_bignumbers x; /* Private key */ +}; + +/* + * DSA public key. dsa_key is the original type from LTC, with type PK_PUBLIC + */ +struct tee_ltc_dsa_public_key { + struct ltc_bignumbers g; /* Base generator */ + struct ltc_bignumbers p; /* Prime modulus */ + struct ltc_bignumbers q; /* Order of subgroup */ + struct ltc_bignumbers y; /* Public key */ +}; + +/* + * DH key pair. dsa_key is the original type from LTC, with type PK_PRIVATE + */ +struct tee_ltc_dh_key_pair { + struct ltc_bignumbers g; /* Base generator */ + struct ltc_bignumbers p; /* Prime modulus */ + struct ltc_bignumbers x; /* Private key */ + struct ltc_bignumbers y; /* Public key */ + + /* other parameters */ + struct ltc_bignumbers q; /* Sub Prime */ + uint32_t xbits; +}; + +#define TEE_TYPE_ATTR_OPTIONAL 0x0 +#define TEE_TYPE_ATTR_REQUIRED 0x1 +#define TEE_TYPE_ATTR_OPTIONAL_GROUP 0x2 +#define TEE_TYPE_ATTR_SIZE_INDICATOR 0x4 +#define TEE_TYPE_ATTR_GEN_KEY_OPT 0x8 +#define TEE_TYPE_ATTR_GEN_KEY_REQ 0x10 + +#define TEE_TYPE_CONV_FUNC_NONE 0 + /* Handle storing of generic secret keys of varying lengths */ +#define TEE_TYPE_CONV_FUNC_SECRET 1 + /* Convert Array of bytes to/from Big Number from mpa (used by LTC). */ +#define TEE_TYPE_CONV_FUNC_BIGINT 2 + /* Convert to/from value attribute depending on direction */ +#define TEE_TYPE_CONV_FUNC_VALUE 4 + +struct tee_cryp_obj_type_attrs { + uint32_t attr_id; + uint16_t flags; + uint16_t conv_func; + uint16_t raw_offs; + uint16_t raw_size; +}; + +#define RAW_DATA(_x, _y) \ + .raw_offs = offsetof(_x, _y), .raw_size = TEE_MEMBER_SIZE(_x, _y) + +static const struct tee_cryp_obj_type_attrs + tee_cryp_obj_secret_value_attrs[] = { + { + .attr_id = TEE_ATTR_SECRET_VALUE, + .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR, + .conv_func = TEE_TYPE_CONV_FUNC_SECRET, + .raw_offs = 0, + .raw_size = 0 + }, +}; + +static const struct tee_cryp_obj_type_attrs tee_cryp_obj_rsa_pub_key_attrs[] = { + { + .attr_id = TEE_ATTR_RSA_MODULUS, + .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR, + .conv_func = TEE_TYPE_CONV_FUNC_BIGINT, + RAW_DATA(struct tee_ltc_rsa_public_key, N) + }, + + { + .attr_id = TEE_ATTR_RSA_PUBLIC_EXPONENT, + .flags = TEE_TYPE_ATTR_REQUIRED, + .conv_func = TEE_TYPE_CONV_FUNC_BIGINT, + RAW_DATA(struct tee_ltc_rsa_public_key, e) + }, +}; + +static const struct tee_cryp_obj_type_attrs tee_cryp_obj_rsa_keypair_attrs[] = { + { + .attr_id = TEE_ATTR_RSA_MODULUS, + .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR, + .conv_func = TEE_TYPE_CONV_FUNC_BIGINT, + RAW_DATA(struct tee_ltc_rsa_key_pair, N) + }, + + { + .attr_id = TEE_ATTR_RSA_PUBLIC_EXPONENT, + .flags = TEE_TYPE_ATTR_REQUIRED, + .conv_func = TEE_TYPE_CONV_FUNC_BIGINT, + RAW_DATA(struct tee_ltc_rsa_key_pair, e) + }, + + { + .attr_id = TEE_ATTR_RSA_PRIVATE_EXPONENT, + .flags = TEE_TYPE_ATTR_REQUIRED, + .conv_func = TEE_TYPE_CONV_FUNC_BIGINT, + RAW_DATA(struct tee_ltc_rsa_key_pair, d) + }, + + { + .attr_id = TEE_ATTR_RSA_PRIME1, + .flags = TEE_TYPE_ATTR_OPTIONAL_GROUP, + .conv_func = TEE_TYPE_CONV_FUNC_BIGINT, + RAW_DATA(struct tee_ltc_rsa_key_pair, p) + }, + + { + .attr_id = TEE_ATTR_RSA_PRIME2, + .flags = TEE_TYPE_ATTR_OPTIONAL_GROUP, + .conv_func = TEE_TYPE_CONV_FUNC_BIGINT, + RAW_DATA(struct tee_ltc_rsa_key_pair, q) + }, + + { + .attr_id = TEE_ATTR_RSA_EXPONENT1, + .flags = TEE_TYPE_ATTR_OPTIONAL_GROUP, + .conv_func = TEE_TYPE_CONV_FUNC_BIGINT, + RAW_DATA(struct tee_ltc_rsa_key_pair, dP) + }, + + { + .attr_id = TEE_ATTR_RSA_EXPONENT2, + .flags = TEE_TYPE_ATTR_OPTIONAL_GROUP, + .conv_func = TEE_TYPE_CONV_FUNC_BIGINT, + RAW_DATA(struct tee_ltc_rsa_key_pair, dQ) + }, + + { + .attr_id = TEE_ATTR_RSA_COEFFICIENT, + .flags = TEE_TYPE_ATTR_OPTIONAL_GROUP, + .conv_func = TEE_TYPE_CONV_FUNC_BIGINT, + RAW_DATA(struct tee_ltc_rsa_key_pair, qP) + }, +}; + +static const struct tee_cryp_obj_type_attrs tee_cryp_obj_dsa_pub_key_attrs[] = { + { + .attr_id = TEE_ATTR_DSA_PRIME, + .flags = TEE_TYPE_ATTR_REQUIRED, + .conv_func = TEE_TYPE_CONV_FUNC_BIGINT, + RAW_DATA(struct tee_ltc_dsa_public_key, p) + }, + + { + .attr_id = TEE_ATTR_DSA_SUBPRIME, + .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR, + .conv_func = TEE_TYPE_CONV_FUNC_BIGINT, + RAW_DATA(struct tee_ltc_dsa_public_key, q) + }, + + { + .attr_id = TEE_ATTR_DSA_BASE, + .flags = TEE_TYPE_ATTR_REQUIRED, + .conv_func = TEE_TYPE_CONV_FUNC_BIGINT, + RAW_DATA(struct tee_ltc_dsa_public_key, g) + }, + + { + .attr_id = TEE_ATTR_DSA_PUBLIC_VALUE, + .flags = TEE_TYPE_ATTR_REQUIRED, + .conv_func = TEE_TYPE_CONV_FUNC_BIGINT, + RAW_DATA(struct tee_ltc_dsa_public_key, y) + }, +}; + +static const struct tee_cryp_obj_type_attrs tee_cryp_obj_dsa_keypair_attrs[] = { + { + .attr_id = TEE_ATTR_DSA_PRIME, + .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_GEN_KEY_REQ, + .conv_func = TEE_TYPE_CONV_FUNC_BIGINT, + RAW_DATA(struct tee_ltc_dsa_key_pair, p) + }, + + { + .attr_id = TEE_ATTR_DSA_SUBPRIME, + .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR | + TEE_TYPE_ATTR_GEN_KEY_REQ, + .conv_func = TEE_TYPE_CONV_FUNC_BIGINT, + RAW_DATA(struct tee_ltc_dsa_key_pair, q) + }, + + { + .attr_id = TEE_ATTR_DSA_BASE, + .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_GEN_KEY_REQ, + .conv_func = TEE_TYPE_CONV_FUNC_BIGINT, + RAW_DATA(struct tee_ltc_dsa_key_pair, g) + }, + + { + .attr_id = TEE_ATTR_DSA_PRIVATE_VALUE, + .flags = TEE_TYPE_ATTR_REQUIRED, + .conv_func = TEE_TYPE_CONV_FUNC_BIGINT, + RAW_DATA(struct tee_ltc_dsa_key_pair, x) + }, + + { + .attr_id = TEE_ATTR_DSA_PUBLIC_VALUE, + .flags = TEE_TYPE_ATTR_REQUIRED, + .conv_func = TEE_TYPE_CONV_FUNC_BIGINT, + RAW_DATA(struct tee_ltc_dsa_key_pair, y) + }, +}; + +static const struct tee_cryp_obj_type_attrs tee_cryp_obj_dh_keypair_attrs[] = { + { + .attr_id = TEE_ATTR_DH_PRIME, + .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR | + TEE_TYPE_ATTR_GEN_KEY_REQ, + .conv_func = TEE_TYPE_CONV_FUNC_BIGINT, + RAW_DATA(struct tee_ltc_dh_key_pair, p) + }, + + { + .attr_id = TEE_ATTR_DH_BASE, + .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_GEN_KEY_REQ, + .conv_func = TEE_TYPE_CONV_FUNC_BIGINT, + RAW_DATA(struct tee_ltc_dh_key_pair, g) + }, + + { + .attr_id = TEE_ATTR_DH_PUBLIC_VALUE, + .flags = TEE_TYPE_ATTR_REQUIRED, + .conv_func = TEE_TYPE_CONV_FUNC_BIGINT, + RAW_DATA(struct tee_ltc_dh_key_pair, y) + }, + + { + .attr_id = TEE_ATTR_DH_PRIVATE_VALUE, + .flags = TEE_TYPE_ATTR_REQUIRED, + .conv_func = TEE_TYPE_CONV_FUNC_BIGINT, + RAW_DATA(struct tee_ltc_dh_key_pair, x) + }, + + { + .attr_id = TEE_ATTR_DH_SUBPRIME, + .flags = TEE_TYPE_ATTR_OPTIONAL_GROUP | TEE_TYPE_ATTR_GEN_KEY_OPT, + .conv_func = TEE_TYPE_CONV_FUNC_BIGINT, + RAW_DATA(struct tee_ltc_dh_key_pair, q) + }, + + { + .attr_id = TEE_ATTR_DH_X_BITS, + .flags = TEE_TYPE_ATTR_GEN_KEY_OPT, + .conv_func = TEE_TYPE_CONV_FUNC_VALUE, + RAW_DATA(struct tee_ltc_dh_key_pair, xbits) + }, +}; + +struct tee_cryp_obj_type_props { + TEE_ObjectType obj_type; + uint16_t min_size; /* may not be smaller than this */ + uint16_t max_size; /* may not be larger than this */ + uint16_t alloc_size; /* this many bytes are allocated to hold data */ + uint8_t quanta; /* may only be an multiple of this */ + + uint8_t num_type_attrs; + const struct tee_cryp_obj_type_attrs *type_attrs; +}; + +#define PROP(obj_type, quanta, min_size, max_size, alloc_size, type_attrs) \ + { (obj_type), (min_size), (max_size), (alloc_size), (quanta), \ + TEE_ARRAY_SIZE(type_attrs), (type_attrs) } + +static const struct tee_cryp_obj_type_props tee_cryp_obj_props[] = { + PROP(TEE_TYPE_AES, 64, 128, 256, /* valid sizes 128, 192, 256 */ + 256 / 8 + sizeof(struct tee_cryp_obj_secret), + tee_cryp_obj_secret_value_attrs), + PROP(TEE_TYPE_DES, 56, 56, 56, + /* + * Valid size 56 without parity, note that we still allocate + * for 64 bits since the key is supplied with parity. + */ + 64 / 8 + sizeof(struct tee_cryp_obj_secret), + tee_cryp_obj_secret_value_attrs), + PROP(TEE_TYPE_DES3, 56, 112, 168, + /* + * Valid sizes 112, 168 without parity, note that we still + * allocate for with space for the parity since the key is + * supplied with parity. + */ + 192 / 8 + sizeof(struct tee_cryp_obj_secret), + tee_cryp_obj_secret_value_attrs), + PROP(TEE_TYPE_HMAC_MD5, 8, 64, 512, + 512 / 8 + sizeof(struct tee_cryp_obj_secret), + tee_cryp_obj_secret_value_attrs), + PROP(TEE_TYPE_HMAC_SHA1, 8, 80, 512, + 512 / 8 + sizeof(struct tee_cryp_obj_secret), + tee_cryp_obj_secret_value_attrs), + PROP(TEE_TYPE_HMAC_SHA224, 8, 112, 512, + 512 / 8 + sizeof(struct tee_cryp_obj_secret), + tee_cryp_obj_secret_value_attrs), + PROP(TEE_TYPE_HMAC_SHA256, 8, 192, 1024, + 1024 / 8 + sizeof(struct tee_cryp_obj_secret), + tee_cryp_obj_secret_value_attrs), + PROP(TEE_TYPE_HMAC_SHA384, 8, 256, 1024, + 1024 / 8 + sizeof(struct tee_cryp_obj_secret), + tee_cryp_obj_secret_value_attrs), + PROP(TEE_TYPE_HMAC_SHA512, 8, 256, 1024, + 1024 / 8 + sizeof(struct tee_cryp_obj_secret), + tee_cryp_obj_secret_value_attrs), + PROP(TEE_TYPE_GENERIC_SECRET, 8, 0, 4096, + 4096 / 8 + sizeof(struct tee_cryp_obj_secret), + tee_cryp_obj_secret_value_attrs), + + PROP(TEE_TYPE_RSA_PUBLIC_KEY, 1, 256, 2048, + sizeof(struct tee_ltc_rsa_public_key), + tee_cryp_obj_rsa_pub_key_attrs), + + PROP(TEE_TYPE_RSA_KEYPAIR, 1, 256, 2048, + sizeof(struct tee_ltc_rsa_key_pair), + tee_cryp_obj_rsa_keypair_attrs), + + PROP(TEE_TYPE_DSA_PUBLIC_KEY, 64, 512, 1024, + sizeof(struct tee_ltc_dsa_public_key), + tee_cryp_obj_dsa_pub_key_attrs), + + PROP(TEE_TYPE_DSA_KEYPAIR, 64, 512, 1024, + sizeof(struct tee_ltc_dsa_key_pair), + tee_cryp_obj_dsa_keypair_attrs), + + PROP(TEE_TYPE_DH_KEYPAIR, 1, 256, 2048, + sizeof(struct tee_ltc_dh_key_pair), + tee_cryp_obj_dh_keypair_attrs), +}; + +/* + * Populate the pointers in ltc_key, given struct tee_ltc_rsa_key_pair + */ +static void tee_populate_rsa_key_pair( + rsa_key *ltc_key, + struct tee_ltc_rsa_key_pair *tee_key, + bool crt) +{ + ltc_key->type = PK_PRIVATE; + ltc_key->e = (char *)&tee_key->e; + ltc_key->d = (char *)&tee_key->d; + ltc_key->N = (char *)&tee_key->N; + + if (crt) { + ltc_key->p = (char *)&tee_key->p; + ltc_key->q = (char *)&tee_key->q; + ltc_key->qP = (char *)&tee_key->qP; + ltc_key->dP = (char *)&tee_key->dP; + ltc_key->dQ = (char *)&tee_key->dQ; + } else { + ltc_key->p = 0; + ltc_key->q = 0; + ltc_key->qP = 0; + ltc_key->dP = 0; + ltc_key->dQ = 0; + } + + SET_MPA_ALLOCSIZE(&tee_key->e); + SET_MPA_ALLOCSIZE(&tee_key->d); + SET_MPA_ALLOCSIZE(&tee_key->N); + SET_MPA_ALLOCSIZE(&tee_key->p); + SET_MPA_ALLOCSIZE(&tee_key->q); + SET_MPA_ALLOCSIZE(&tee_key->qP); + SET_MPA_ALLOCSIZE(&tee_key->dP); + SET_MPA_ALLOCSIZE(&tee_key->dQ); +} + +static void tee_populate_rsa_public_key( + rsa_key *ltc_key, + struct tee_ltc_rsa_public_key *tee_key) +{ + ltc_key->type = PK_PUBLIC; + ltc_key->e = (char *)&tee_key->e; + ltc_key->N = (char *)&tee_key->N; + SET_MPA_ALLOCSIZE(&tee_key->e); + SET_MPA_ALLOCSIZE(&tee_key->N); +} + +static void tee_populate_dsa_key_pair( + dsa_key *ltc_key, + struct tee_ltc_dsa_key_pair *tee_key) +{ + ltc_key->type = PK_PRIVATE; + ltc_key->g = (char *)&tee_key->g; + ltc_key->p = (char *)&tee_key->p; + ltc_key->q = (char *)&tee_key->q; + ltc_key->y = (char *)&tee_key->y; + ltc_key->x = (char *)&tee_key->x; + + SET_MPA_ALLOCSIZE(&tee_key->g); + SET_MPA_ALLOCSIZE(&tee_key->p); + SET_MPA_ALLOCSIZE(&tee_key->q); + SET_MPA_ALLOCSIZE(&tee_key->y); + SET_MPA_ALLOCSIZE(&tee_key->x); + + ltc_key->qord = mp_unsigned_bin_size(&tee_key->g); +} + +static void tee_populate_dsa_public_key( + dsa_key *ltc_key, + struct tee_ltc_dsa_public_key *tee_key) +{ + ltc_key->type = PK_PUBLIC; + ltc_key->g = (char *)&tee_key->g; + ltc_key->p = (char *)&tee_key->p; + ltc_key->q = (char *)&tee_key->q; + ltc_key->y = (char *)&tee_key->y; + + SET_MPA_ALLOCSIZE(&tee_key->g); + SET_MPA_ALLOCSIZE(&tee_key->p); + SET_MPA_ALLOCSIZE(&tee_key->q); + SET_MPA_ALLOCSIZE(&tee_key->y); + + ltc_key->qord = mp_unsigned_bin_size(&tee_key->g); +} + +static void tee_populate_dh_key_pair( + dh_key *ltc_key, + struct tee_ltc_dh_key_pair *tee_key) +{ + ltc_key->type = PK_PRIVATE; + ltc_key->g = (char *)&tee_key->g; + ltc_key->p = (char *)&tee_key->p; + ltc_key->x = (char *)&tee_key->x; + ltc_key->y = (char *)&tee_key->y; + + SET_MPA_ALLOCSIZE(&tee_key->g); + SET_MPA_ALLOCSIZE(&tee_key->p); + SET_MPA_ALLOCSIZE(&tee_key->x); + SET_MPA_ALLOCSIZE(&tee_key->y); + + /* + * q and xbits are not part of the dh key. They are only used to + * generate a key pair + * Alloc size must be set on 'q' anyway + */ + SET_MPA_ALLOCSIZE(&tee_key->q); +} + +TEE_Result tee_svc_cryp_obj_get_info(uint32_t obj, TEE_ObjectInfo *info) +{ + TEE_Result res; + struct tee_ta_session *sess; + struct tee_obj *o; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_obj_get(sess->ctx, obj, &o); + if (res != TEE_SUCCESS) + return res; + + return tee_svc_copy_to_user(sess, info, &o->info, sizeof(o->info)); +} + +TEE_Result tee_svc_cryp_obj_restrict_usage(uint32_t obj, uint32_t usage) +{ + TEE_Result res; + struct tee_ta_session *sess; + struct tee_obj *o; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_obj_get(sess->ctx, obj, &o); + if (res != TEE_SUCCESS) + return res; + + o->info.objectUsage &= usage; + + return TEE_SUCCESS; +} + +static TEE_Result tee_svc_cryp_obj_get_raw_data( + struct tee_obj *o, + const struct tee_cryp_obj_type_props *type_props, + size_t idx, void **data, size_t *size) +{ + const struct tee_cryp_obj_type_attrs *type_attr = + type_props->type_attrs + idx; + if (type_attr->raw_size == 0) { + struct tee_cryp_obj_secret *key = + (struct tee_cryp_obj_secret *)o->data; + + /* Handle generic secret */ + if (type_attr->raw_offs != 0) + return TEE_ERROR_BAD_STATE; + *size = key->key_size; + } else { + *size = type_attr->raw_size; + } + *data = (uint8_t *)o->data + type_attr->raw_offs; + return TEE_SUCCESS; +} + +static int tee_svc_cryp_obj_find_type_attr_idx( + uint32_t attr_id, + const struct tee_cryp_obj_type_props *type_props) +{ + size_t n; + + for (n = 0; n < type_props->num_type_attrs; n++) { + if (attr_id == type_props->type_attrs[n].attr_id) + return n; + } + return -1; +} + +static const struct tee_cryp_obj_type_props *tee_svc_find_type_props( + TEE_ObjectType obj_type) +{ + size_t n; + + for (n = 0; n < TEE_ARRAY_SIZE(tee_cryp_obj_props); n++) { + if (tee_cryp_obj_props[n].obj_type == obj_type) + return tee_cryp_obj_props + n; + } + + return NULL; +} + +static TEE_Result tee_svc_cryp_obj_copy_out(struct tee_ta_session *sess, + void *buffer, size_t *size, + uint16_t conv_func, + void *raw_data, + size_t raw_data_size) +{ + TEE_Result res; + size_t s; + + res = tee_svc_copy_from_user(sess, &s, size, sizeof(size_t)); + if (res != TEE_SUCCESS) + return res; + + switch (conv_func) { + case TEE_TYPE_CONV_FUNC_NONE: + res = + tee_svc_copy_to_user(sess, size, &raw_data_size, + sizeof(size_t)); + if (res != TEE_SUCCESS) + return res; + + if (s < raw_data_size) + return TEE_ERROR_SHORT_BUFFER; + + return tee_svc_copy_to_user(sess, buffer, raw_data, + raw_data_size); + case TEE_TYPE_CONV_FUNC_SECRET: + { + struct tee_cryp_obj_secret *obj; + size_t key_size; + + if (!TEE_ALIGNMENT_IS_OK + (raw_data, struct tee_cryp_obj_secret)) + return TEE_ERROR_BAD_STATE; + obj = (struct tee_cryp_obj_secret *)(void *)raw_data; + key_size = obj->key_size; + + res = + tee_svc_copy_to_user(sess, size, &key_size, + sizeof(size_t)); + if (res != TEE_SUCCESS) + return res; + + if (s < key_size) + return TEE_ERROR_SHORT_BUFFER; + + return tee_svc_copy_to_user(sess, buffer, obj + 1, + key_size); + } + + case TEE_TYPE_CONV_FUNC_BIGINT: + { + size_t req_size; + + SET_MPA_ALLOCSIZE(raw_data); + req_size = mp_unsigned_bin_size(raw_data); + if (req_size == 0) + return TEE_SUCCESS; + res = tee_svc_copy_to_user( + sess, size, &req_size, sizeof(size_t)); + if (res != TEE_SUCCESS) + return res; + + /* Check that the converted result fits the user buffer. */ + if (s < req_size) + return TEE_ERROR_SHORT_BUFFER; + + /* Check we can access data using supplied user mode pointer */ + res = tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t)buffer, + req_size); + if (res != TEE_SUCCESS) + return res; + + /* + * write the mpa number (stored in raw data) into an array of + * bytes (stored in buffer) + */ + mp_to_unsigned_bin(raw_data, buffer); + return TEE_SUCCESS; + } + + case TEE_TYPE_CONV_FUNC_VALUE: + { + uint32_t value[2] = { 0, 0 }; + size_t n = sizeof(value); + + /* + * a value attribute consists of two uint32 but have not + * seen anything that actaully would need that so this + * fills in one with data and the other with zero + */ + TEE_ASSERT(raw_data_size == sizeof(uint32_t)); + value[0] = *(uint32_t *)raw_data; + + res = + tee_svc_copy_to_user(sess, size, &n, + sizeof(size_t)); + if (res != TEE_SUCCESS) + return res; + + /* Check that the converted result fits the user buf */ + if (s < n) + return TEE_ERROR_SHORT_BUFFER; + + return tee_svc_copy_to_user(sess, buffer, &value, n); + } + default: + return TEE_ERROR_BAD_STATE; + } + +} + +TEE_Result tee_svc_cryp_obj_get_attr(uint32_t obj, uint32_t attr_id, + void *buffer, size_t *size) +{ + TEE_Result res; + struct tee_ta_session *sess; + struct tee_obj *o; + const struct tee_cryp_obj_type_props *type_props; + int idx; + size_t raw_size; + void *raw_data; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_obj_get(sess->ctx, obj, &o); + if (res != TEE_SUCCESS) + return TEE_ERROR_ITEM_NOT_FOUND; + + /* Check that the object is initialized */ + if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) + return TEE_ERROR_ITEM_NOT_FOUND; + + /* Check that getting the attribute is allowed */ + if ((attr_id & TEE_ATTR_BIT_PROTECTED) == 0 && + (o->info.objectUsage & TEE_USAGE_EXTRACTABLE) == 0) + return TEE_ERROR_ACCESS_DENIED; + + type_props = tee_svc_find_type_props(o->info.objectType); + if (type_props == NULL) { + /* Unknown object type, "can't happen" */ + return TEE_ERROR_BAD_STATE; + } + + idx = tee_svc_cryp_obj_find_type_attr_idx(attr_id, type_props); + if ((idx < 0) || ((o->have_attrs & (1 << idx)) == 0)) + return TEE_ERROR_ITEM_NOT_FOUND; + + res = tee_svc_cryp_obj_get_raw_data(o, type_props, idx, + &raw_data, &raw_size); + if (res != TEE_SUCCESS) + return res; + + return tee_svc_cryp_obj_copy_out(sess, buffer, size, + type_props->type_attrs[idx].conv_func, + raw_data, raw_size); +} + +TEE_Result tee_svc_cryp_obj_alloc(TEE_ObjectType obj_type, + uint32_t max_obj_size, uint32_t *obj) +{ + TEE_Result res; + struct tee_ta_session *sess; + const struct tee_cryp_obj_type_props *type_props; + struct tee_obj *o; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + /* + * Verify that maxObjectSize is supported and find out how + * much should be allocated. + */ + + /* Find description of object */ + type_props = tee_svc_find_type_props(obj_type); + if (type_props == NULL) + return TEE_ERROR_NOT_SUPPORTED; + + /* Check that maxObjectSize follows restrictions */ + if (max_obj_size % type_props->quanta != 0) + return TEE_ERROR_NOT_SUPPORTED; + if (max_obj_size < type_props->min_size) + return TEE_ERROR_NOT_SUPPORTED; + if (max_obj_size > type_props->max_size) + return TEE_ERROR_NOT_SUPPORTED; + + o = calloc(1, sizeof(*o)); + if (o == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + o->data = calloc(1, type_props->alloc_size); + if (o->data == NULL) { + free(o); + return TEE_ERROR_OUT_OF_MEMORY; + } + o->data_size = type_props->alloc_size; + + o->info.objectType = obj_type; + o->info.maxObjectSize = max_obj_size; + o->info.objectUsage = TEE_USAGE_DEFAULT; + o->info.handleFlags = 0; + + tee_obj_add(sess->ctx, o); + + res = tee_svc_copy_to_user(sess, obj, &o, sizeof(o)); + if (res != TEE_SUCCESS) + tee_obj_close(sess->ctx, o); + return res; +} + +TEE_Result tee_svc_cryp_obj_close(uint32_t obj) +{ + TEE_Result res; + struct tee_ta_session *sess; + struct tee_obj *o; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_obj_get(sess->ctx, obj, &o); + if (res != TEE_SUCCESS) + return res; + + /* + * If it's busy it's used by an operation, a client should never have + * this handle. + */ + if (o->busy) + return TEE_ERROR_ITEM_NOT_FOUND; + + tee_obj_close(sess->ctx, o); + return TEE_SUCCESS; +} + +TEE_Result tee_svc_cryp_obj_reset(uint32_t obj) +{ + TEE_Result res; + struct tee_ta_session *sess; + struct tee_obj *o; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_obj_get(sess->ctx, obj, &o); + if (res != TEE_SUCCESS) + return res; + + if ((o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) == 0) { + memset(o->data, 0, o->data_size); + o->info.objectSize = 0; + o->info.objectUsage = TEE_USAGE_DEFAULT; + } else { + return TEE_ERROR_BAD_PARAMETERS; + } + + return TEE_SUCCESS; +} + +static TEE_Result tee_svc_cryp_obj_store_attr_raw(struct tee_ta_session *sess, + uint16_t conv_func, + const TEE_Attribute *attr, + void *data, size_t data_size) +{ + TEE_Result res; + + if (attr == NULL) + return TEE_ERROR_BAD_STATE; + + if (conv_func != TEE_TYPE_CONV_FUNC_VALUE && + attr->content.ref.buffer == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + switch (conv_func) { + case TEE_TYPE_CONV_FUNC_NONE: + /* No conversion data size has to match exactly */ + if (attr->content.ref.length != data_size) + return TEE_ERROR_BAD_PARAMETERS; + return tee_svc_copy_from_user(sess, data, + attr->content.ref.buffer, + data_size); + case TEE_TYPE_CONV_FUNC_SECRET: + { + struct tee_cryp_obj_secret *obj; + + if (!TEE_ALIGNMENT_IS_OK + (data, struct tee_cryp_obj_secret)) + return TEE_ERROR_BAD_STATE; + obj = (struct tee_cryp_obj_secret *)(void *)data; + + /* Data size has to fit in allocated buffer */ + if (attr->content.ref.length > + (data_size - sizeof(struct tee_cryp_obj_secret))) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_svc_copy_from_user(sess, obj + 1, + attr->content.ref.buffer, + attr->content.ref.length); + if (res == TEE_SUCCESS) + obj->key_size = attr->content.ref.length; + return res; + } + + case TEE_TYPE_CONV_FUNC_BIGINT: + /* + * Check that the converted result fits in the + * allocated buffer + */ + if (attr->content.ref.length > + (data_size + + sizeof(uint32_t) * MPA_NUMBASE_METADATA_SIZE_IN_U32)) + return TEE_ERROR_BAD_PARAMETERS; + + /* Check data can be accessed */ + res = tee_mmu_check_access_rights( + sess->ctx, + TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t)attr->content.ref.buffer, + attr->content.ref.length); + if (res != TEE_SUCCESS) + return res; + + /* + * read the array of bytes (stored in attr->content.ref.buffer) + * and save it as a mpa number (stored in data) + */ + SET_MPA_ALLOCSIZE(data); + mp_read_unsigned_bin( + data, + attr->content.ref.buffer, + attr->content.ref.length); + return TEE_SUCCESS; + + case TEE_TYPE_CONV_FUNC_VALUE: + /* + * a value attribute consists of two uint32 but have not + * seen anything that actaully would need that so this fills + * the data from the first value and discards the second value + */ + *(uint32_t *)data = attr->content.value.a; + + return TEE_SUCCESS; + + default: + return TEE_ERROR_BAD_STATE; + } +} + +enum attr_usage { + ATTR_USAGE_POPULATE, + ATTR_USAGE_GENERATE_KEY +}; + +static TEE_Result tee_svc_cryp_check_attr( + enum attr_usage usage, + const struct tee_cryp_obj_type_props *type_props, + TEE_Attribute *attrs, + uint32_t attr_count) +{ + uint32_t required_flag; + uint32_t opt_flag; + bool all_opt_needed; + uint32_t req_attrs = 0; + uint32_t opt_grp_attrs = 0; + uint32_t attrs_found = 0; + size_t n; + + if (usage == ATTR_USAGE_POPULATE) { + required_flag = TEE_TYPE_ATTR_REQUIRED; + opt_flag = TEE_TYPE_ATTR_OPTIONAL_GROUP; + all_opt_needed = true; + } else { + required_flag = TEE_TYPE_ATTR_GEN_KEY_REQ; + opt_flag = TEE_TYPE_ATTR_GEN_KEY_OPT; + all_opt_needed = false; + } + + /* + * First find out which attributes are required and which belong to + * the optional group + */ + for (n = 0; n < type_props->num_type_attrs; n++) { + uint32_t bit = 1 << n; + uint32_t flags = type_props->type_attrs[n].flags; + + if (flags & required_flag) + req_attrs |= bit; + else if (flags & opt_flag) + opt_grp_attrs |= bit; + } + + /* + * Verify that all required attributes are in place and + * that the same attribute isn't repeated. + */ + for (n = 0; n < attr_count; n++) { + int idx = + tee_svc_cryp_obj_find_type_attr_idx(attrs[n].attributeID, + type_props); + if (idx >= 0) { + uint32_t bit = 1 << idx; + + if ((attrs_found & bit) != 0) + return TEE_ERROR_ITEM_NOT_FOUND; + + attrs_found |= bit; + } + } + /* Required attribute missing */ + if ((attrs_found & req_attrs) != req_attrs) + return TEE_ERROR_ITEM_NOT_FOUND; + + /* + * If the flag says that "if one of the optional attributes are included + * all of them has to be included" this must be checked. + */ + if (all_opt_needed && (attrs_found & opt_grp_attrs) != 0 && + (attrs_found & opt_grp_attrs) != opt_grp_attrs) + return TEE_ERROR_ITEM_NOT_FOUND; + + return TEE_SUCCESS; +} + +static TEE_Result tee_svc_cryp_obj_populate_type( + struct tee_ta_session *sess, + struct tee_obj *o, + const struct tee_cryp_obj_type_props *type_props, + const TEE_Attribute *attrs, + uint32_t attr_count) +{ + TEE_Result res; + uint32_t have_attrs = 0; + size_t obj_size = 0; + size_t n; + + for (n = 0; n < attr_count; n++) { + size_t raw_size; + void *raw_data; + int idx = + tee_svc_cryp_obj_find_type_attr_idx(attrs[n].attributeID, + type_props); + if (idx < 0) + continue; + + have_attrs |= 1 << idx; + + res = tee_svc_cryp_obj_get_raw_data(o, type_props, idx, + &raw_data, &raw_size); + if (res != TEE_SUCCESS) + return res; + + res = + tee_svc_cryp_obj_store_attr_raw( + sess, type_props->type_attrs[idx].conv_func, + attrs + n, raw_data, raw_size); + if (res != TEE_SUCCESS) + return res; + + /* + * First attr_idx signifies the attribute that gives the size + * of the object + */ + if (type_props->type_attrs[idx].flags & + TEE_TYPE_ATTR_SIZE_INDICATOR) { + obj_size += attrs[n].content.ref.length * 8; + } + } + + /* + * We have to do it like this because the parity bits aren't counted + * when telling the size of the key in bits. + */ + if (o->info.objectType == TEE_TYPE_DES || + o->info.objectType == TEE_TYPE_DES3) + obj_size -= obj_size / 8; /* Exclude parity in size of key */ + + o->have_attrs = have_attrs; + o->info.objectSize = obj_size; + return TEE_SUCCESS; +} + +TEE_Result tee_svc_cryp_obj_populate(uint32_t obj, TEE_Attribute *attrs, + uint32_t attr_count) +{ + TEE_Result res; + struct tee_ta_session *sess; + struct tee_obj *o; + const struct tee_cryp_obj_type_props *type_props; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_obj_get(sess->ctx, obj, &o); + if (res != TEE_SUCCESS) + return res; + + /* Must be a transient object */ + if ((o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) != 0) + return TEE_ERROR_BAD_PARAMETERS; + + /* Must not be initialized already */ + if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) != 0) + return TEE_ERROR_BAD_PARAMETERS; + + type_props = tee_svc_find_type_props(o->info.objectType); + if (type_props == NULL) + return TEE_ERROR_NOT_IMPLEMENTED; + + res = tee_svc_cryp_check_attr(ATTR_USAGE_POPULATE, type_props, attrs, + attr_count); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_cryp_obj_populate_type(sess, o, type_props, attrs, + attr_count); + if (res == TEE_SUCCESS) + o->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; + + return res; +} + +TEE_Result tee_svc_cryp_obj_copy(uint32_t dst, uint32_t src) +{ + TEE_Result res; + struct tee_ta_session *sess; + struct tee_obj *dst_o; + struct tee_obj *src_o; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_obj_get(sess->ctx, dst, &dst_o); + if (res != TEE_SUCCESS) + return res; + + res = tee_obj_get(sess->ctx, src, &src_o); + if (res != TEE_SUCCESS) + return res; + + if ((src_o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) + return TEE_ERROR_BAD_PARAMETERS; + if ((dst_o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) != 0) + return TEE_ERROR_BAD_PARAMETERS; + if ((dst_o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) != 0) + return TEE_ERROR_BAD_PARAMETERS; + + if (dst_o->info.objectType == src_o->info.objectType) { + /* Generic case */ + if (dst_o->data_size != src_o->data_size) + return TEE_ERROR_BAD_STATE; + dst_o->have_attrs = src_o->have_attrs; + memcpy(dst_o->data, src_o->data, src_o->data_size); + + } else if (dst_o->info.objectType == TEE_TYPE_RSA_PUBLIC_KEY && + src_o->info.objectType == TEE_TYPE_RSA_KEYPAIR) { + /* Extract public key from RSA key pair */ + struct tee_ltc_rsa_key_pair *key_pair = src_o->data; + struct tee_ltc_rsa_public_key *pub_key = dst_o->data; + size_t n; + + memcpy(&pub_key->e, &key_pair->e, sizeof(pub_key->e)); + memcpy(&pub_key->N, &key_pair->N, sizeof(pub_key->N)); + + /* Set the attributes */ + dst_o->have_attrs = 0; + for (n = 0; n < TEE_ARRAY_SIZE(tee_cryp_obj_rsa_pub_key_attrs); + n++) + dst_o->have_attrs |= 1 << n; + + } else if (dst_o->info.objectType == TEE_TYPE_DSA_PUBLIC_KEY && + src_o->info.objectType == TEE_TYPE_DSA_KEYPAIR) { + /* Extract public key from DSA key pair */ + struct tee_ltc_dsa_key_pair *key_pair = src_o->data; + struct tee_ltc_dsa_public_key *pub_key = dst_o->data; + size_t n; + + memcpy(&pub_key->g, &key_pair->g, sizeof(pub_key->g)); + memcpy(&pub_key->p, &key_pair->p, sizeof(pub_key->p)); + memcpy(&pub_key->q, &key_pair->q, sizeof(pub_key->q)); + memcpy(&pub_key->y, &key_pair->y, sizeof(pub_key->y)); + + /* Set the attributes */ + dst_o->have_attrs = 0; + for (n = 0; n < TEE_ARRAY_SIZE(tee_cryp_obj_dsa_pub_key_attrs); + n++) + dst_o->have_attrs |= 1 << n; + + } else + return TEE_ERROR_BAD_PARAMETERS; + + dst_o->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; + dst_o->info.objectSize = src_o->info.objectSize; + dst_o->info.objectUsage = src_o->info.objectUsage; + return TEE_SUCCESS; +} + +static TEE_Result tee_svc_obj_generate_key_rsa( + struct tee_obj *o, const struct tee_cryp_obj_type_props *type_props, + uint32_t key_size) +{ + TEE_Result res; + struct tee_ltc_rsa_key_pair *tee_rsa_key; + rsa_key ltc_rsa_key; + + TEE_ASSERT(sizeof(struct tee_ltc_rsa_key_pair) == o->data_size); + tee_rsa_key = (struct tee_ltc_rsa_key_pair *)o->data; + tee_populate_rsa_key_pair(<c_rsa_key, tee_rsa_key, true); + res = tee_acipher_gen_rsa_keys(<c_rsa_key, key_size); + if (res != TEE_SUCCESS) + return res; + + /* Set bits for all known attributes for this object type */ + o->have_attrs = (1 << type_props->num_type_attrs) - 1; + return TEE_SUCCESS; +} + +static TEE_Result tee_svc_obj_generate_key_dsa( + struct tee_obj *o, const struct tee_cryp_obj_type_props *type_props, + uint32_t key_size) +{ + TEE_Result res; + struct tee_ltc_dsa_key_pair *tee_dsa_key; + dsa_key ltc_dsa_key; + + TEE_ASSERT(sizeof(struct tee_ltc_dsa_key_pair) == o->data_size); + tee_dsa_key = (struct tee_ltc_dsa_key_pair *)o->data; + tee_populate_dsa_key_pair(<c_dsa_key, tee_dsa_key); + res = tee_acipher_gen_dsa_keys(<c_dsa_key, key_size); + if (res != TEE_SUCCESS) + return res; + + /* Set bits for all known attributes for this object type */ + o->have_attrs = (1 << type_props->num_type_attrs) - 1; + return TEE_SUCCESS; +} + +static TEE_Result tee_svc_obj_generate_key_dh( + struct tee_ta_session *sess, + struct tee_obj *o, const struct tee_cryp_obj_type_props *type_props, + uint32_t key_size, const TEE_Attribute *params, uint32_t param_count) +{ + TEE_Result res; + struct tee_ltc_dh_key_pair *tee_dh_key; + dh_key ltc_dh_key; + struct ltc_bignumbers *dh_q = NULL; + uint32_t dh_xbits = 0; + + TEE_ASSERT(sizeof(struct tee_ltc_dh_key_pair) == o->data_size); + + /* Copy the present attributes into the obj before starting */ + res = tee_svc_cryp_obj_populate_type( + sess, o, type_props, params, param_count); + if (res != TEE_SUCCESS) + return res; + + tee_dh_key = (struct tee_ltc_dh_key_pair *)o->data; + tee_populate_dh_key_pair(<c_dh_key, tee_dh_key); + + if (GET_ATTRIBUTE(o, type_props, TEE_ATTR_DH_SUBPRIME)) + dh_q = &tee_dh_key->q; + if (GET_ATTRIBUTE(o, type_props, TEE_ATTR_DH_X_BITS)) + dh_xbits = tee_dh_key->xbits; + res = tee_acipher_gen_dh_keys(<c_dh_key, dh_q, dh_xbits); + if (res != TEE_SUCCESS) + return res; + + /* Set bits for the generated public and private key */ + SET_ATTRIBUTE(o, type_props, TEE_ATTR_DH_PUBLIC_VALUE); + SET_ATTRIBUTE(o, type_props, TEE_ATTR_DH_PRIVATE_VALUE); + SET_ATTRIBUTE(o, type_props, TEE_ATTR_DH_X_BITS); + return TEE_SUCCESS; +} + +TEE_Result tee_svc_obj_generate_key( + uint32_t obj, uint32_t key_size, + const TEE_Attribute *params, uint32_t param_count) +{ + TEE_Result res; + struct tee_ta_session *sess; + const struct tee_cryp_obj_type_props *type_props; + struct tee_obj *o; + struct tee_cryp_obj_secret *key; + size_t byte_size; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_obj_get(sess->ctx, obj, &o); + if (res != TEE_SUCCESS) + return res; + + /* Must be a transient object */ + if ((o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) != 0) + return TEE_ERROR_BAD_STATE; + + /* Must not be initialized already */ + if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) != 0) + return TEE_ERROR_BAD_STATE; + + /* Find description of object */ + type_props = tee_svc_find_type_props(o->info.objectType); + if (type_props == NULL) + return TEE_ERROR_NOT_SUPPORTED; + + /* Check that maxObjectSize follows restrictions */ + if (key_size % type_props->quanta != 0) + return TEE_ERROR_NOT_SUPPORTED; + if (key_size < type_props->min_size) + return TEE_ERROR_NOT_SUPPORTED; + if (key_size > type_props->max_size) + return TEE_ERROR_NOT_SUPPORTED; + + res = tee_svc_cryp_check_attr(ATTR_USAGE_GENERATE_KEY, type_props, + (TEE_Attribute *)params, param_count); + if (res != TEE_SUCCESS) + return res; + + switch (o->info.objectType) { + case TEE_TYPE_AES: + case TEE_TYPE_DES: + case TEE_TYPE_DES3: + case TEE_TYPE_HMAC_MD5: + case TEE_TYPE_HMAC_SHA1: + case TEE_TYPE_HMAC_SHA224: + case TEE_TYPE_HMAC_SHA256: + case TEE_TYPE_HMAC_SHA384: + case TEE_TYPE_HMAC_SHA512: + case TEE_TYPE_GENERIC_SECRET: + byte_size = key_size / 8; + + /* + * We have to do it like this because the parity bits aren't + * counted when telling the size of the key in bits. + */ + if (o->info.objectType == TEE_TYPE_DES || + o->info.objectType == TEE_TYPE_DES3) { + byte_size = (key_size + key_size / 7) / 8; + } + + key = (struct tee_cryp_obj_secret *)o->data; + if (byte_size > (o->data_size - sizeof(*key))) + return TEE_ERROR_EXCESS_DATA; + + res = get_rng_array((void *)(key + 1), byte_size); + if (res != TEE_SUCCESS) + return res; + + /* Force the last bit to have exactly a value on byte_size */ + ((char *)key)[sizeof(key->key_size) + byte_size - 1] |= 0x80; + key->key_size = byte_size; + + /* Set bits for all known attributes for this object type */ + o->have_attrs = (1 << type_props->num_type_attrs) - 1; + + break; + + case TEE_TYPE_RSA_KEYPAIR: + res = tee_svc_obj_generate_key_rsa(o, type_props, key_size); + if (res != TEE_SUCCESS) + return res; + break; + + case TEE_TYPE_DSA_KEYPAIR: + res = tee_svc_obj_generate_key_dsa(o, type_props, key_size); + if (res != TEE_SUCCESS) + return res; + break; + + case TEE_TYPE_DH_KEYPAIR: + res = tee_svc_obj_generate_key_dh( + sess, o, type_props, key_size, params, param_count); + if (res != TEE_SUCCESS) + return res; + break; + + default: + return TEE_ERROR_BAD_FORMAT; + } + + o->info.objectSize = key_size; + o->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; + return TEE_SUCCESS; +} + +static TEE_Result tee_svc_cryp_get_state(struct tee_ta_session *sess, + uint32_t state_id, + struct tee_cryp_state **state) +{ + struct tee_cryp_state *s; + + TAILQ_FOREACH(s, &sess->ctx->cryp_states, link) { + if (state_id == (uint32_t) s) { + *state = s; + return TEE_SUCCESS; + } + } + return TEE_ERROR_BAD_PARAMETERS; +} + +static void cryp_state_free(struct tee_ta_ctx *ctx, struct tee_cryp_state *cs) +{ + struct tee_obj *o; + + if (tee_obj_get(ctx, cs->key1, &o) == TEE_SUCCESS) + tee_obj_close(ctx, o); + if (tee_obj_get(ctx, cs->key2, &o) == TEE_SUCCESS) + tee_obj_close(ctx, o); + + TAILQ_REMOVE(&ctx->cryp_states, cs, link); + if (cs->ctx_finalize != NULL) + cs->ctx_finalize(cs->ctx, cs->algo); + free(cs->ctx); + free(cs); +} + +static TEE_Result tee_svc_cryp_check_key_type(const struct tee_obj *o, + uint32_t algo, + TEE_OperationMode mode) +{ + uint32_t req_key_type; + + switch (TEE_ALG_GET_MAIN_ALG(algo)) { + case TEE_MAIN_ALGO_MD5: + req_key_type = TEE_TYPE_HMAC_MD5; + break; + case TEE_MAIN_ALGO_SHA1: + req_key_type = TEE_TYPE_HMAC_SHA1; + break; + case TEE_MAIN_ALGO_SHA224: + req_key_type = TEE_TYPE_HMAC_SHA224; + break; + case TEE_MAIN_ALGO_SHA256: + req_key_type = TEE_TYPE_HMAC_SHA256; + break; + case TEE_MAIN_ALGO_SHA384: + req_key_type = TEE_TYPE_HMAC_SHA384; + break; + case TEE_MAIN_ALGO_SHA512: + req_key_type = TEE_TYPE_HMAC_SHA512; + break; + case TEE_MAIN_ALGO_AES: + req_key_type = TEE_TYPE_AES; + break; + case TEE_MAIN_ALGO_DES: + req_key_type = TEE_TYPE_DES; + break; + case TEE_MAIN_ALGO_DES3: + req_key_type = TEE_TYPE_DES3; + break; + case TEE_MAIN_ALGO_RSA: + if (mode == TEE_MODE_ENCRYPT || mode == TEE_MODE_VERIFY) + req_key_type = TEE_TYPE_RSA_PUBLIC_KEY; + else + req_key_type = TEE_TYPE_RSA_KEYPAIR; + break; + case TEE_MAIN_ALGO_DSA: + if (mode == TEE_MODE_ENCRYPT || mode == TEE_MODE_VERIFY) + req_key_type = TEE_TYPE_DSA_PUBLIC_KEY; + else + req_key_type = TEE_TYPE_DSA_KEYPAIR; + break; + case TEE_MAIN_ALGO_DH: + req_key_type = TEE_TYPE_DH_KEYPAIR; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + if (req_key_type != o->info.objectType) + return TEE_ERROR_BAD_PARAMETERS; + return TEE_SUCCESS; +} + +TEE_Result tee_svc_cryp_state_alloc(uint32_t algo, uint32_t mode, + uint32_t key1, uint32_t key2, + uint32_t *state) +{ + TEE_Result res; + struct tee_cryp_state *cs; + struct tee_ta_session *sess; + struct tee_obj *o1 = NULL; + struct tee_obj *o2 = NULL; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + if (key1 != 0) { + res = tee_obj_get(sess->ctx, key1, &o1); + if (res != TEE_SUCCESS) + return res; + if (o1->busy) + return TEE_ERROR_BAD_PARAMETERS; + res = tee_svc_cryp_check_key_type(o1, algo, mode); + if (res != TEE_SUCCESS) + return res; + } + if (key2 != 0) { + res = tee_obj_get(sess->ctx, key2, &o2); + if (res != TEE_SUCCESS) + return res; + if (o2->busy) + return TEE_ERROR_BAD_PARAMETERS; + res = tee_svc_cryp_check_key_type(o2, algo, mode); + if (res != TEE_SUCCESS) + return res; + } + + cs = calloc(1, sizeof(struct tee_cryp_state)); + if (cs == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + TAILQ_INSERT_TAIL(&sess->ctx->cryp_states, cs, link); + cs->algo = algo; + cs->mode = mode; + + switch (TEE_ALG_GET_CLASS(algo)) { + case TEE_OPERATION_CIPHER: + if ((algo == TEE_ALG_AES_XTS && (key1 == 0 || key2 == 0)) || + (algo != TEE_ALG_AES_XTS && (key1 == 0 || key2 != 0))) { + res = TEE_ERROR_BAD_PARAMETERS; + } else { + res = tee_cipher_get_ctx_size(algo, &cs->ctx_size); + if (res != TEE_SUCCESS) + break; + cs->ctx = calloc(1, cs->ctx_size); + if (cs->ctx == NULL) + res = TEE_ERROR_OUT_OF_MEMORY; + } + break; + case TEE_OPERATION_AE: + if (key1 == 0 || key2 != 0) { + res = TEE_ERROR_BAD_PARAMETERS; + } else { + res = tee_authenc_get_ctx_size(algo, &cs->ctx_size); + if (res != TEE_SUCCESS) + break; + cs->ctx = calloc(1, cs->ctx_size); + if (cs->ctx == NULL) + res = TEE_ERROR_OUT_OF_MEMORY; + } + break; + case TEE_OPERATION_MAC: + if (key1 == 0 || key2 != 0) { + res = TEE_ERROR_BAD_PARAMETERS; + } else { + res = tee_mac_get_ctx_size(algo, &cs->ctx_size); + if (res != TEE_SUCCESS) + break; + cs->ctx = calloc(1, cs->ctx_size); + if (cs->ctx == NULL) + res = TEE_ERROR_OUT_OF_MEMORY; + } + break; + case TEE_OPERATION_DIGEST: + if (key1 != 0 || key2 != 0) { + res = TEE_ERROR_BAD_PARAMETERS; + } else { + res = tee_hash_get_ctx_size(algo, &cs->ctx_size); + if (res != TEE_SUCCESS) + break; + cs->ctx = calloc(1, cs->ctx_size); + if (cs->ctx == NULL) + res = TEE_ERROR_OUT_OF_MEMORY; + } + break; + case TEE_OPERATION_ASYMMETRIC_CIPHER: + case TEE_OPERATION_ASYMMETRIC_SIGNATURE: + if (key1 == 0 || key2 != 0) + res = TEE_ERROR_BAD_PARAMETERS; + break; + case TEE_OPERATION_KEY_DERIVATION: + if (key1 == 0 || key2 != 0) + res = TEE_ERROR_BAD_PARAMETERS; + break; + default: + res = TEE_ERROR_NOT_SUPPORTED; + break; + } + if (res != TEE_SUCCESS) + goto out; + + res = tee_svc_copy_to_user(sess, state, &cs, sizeof(uint32_t)); + if (res != TEE_SUCCESS) + goto out; + + /* Register keys */ + if (o1 != NULL) { + o1->busy = true; + cs->key1 = key1; + } + if (o2 != NULL) { + o2->busy = true; + cs->key2 = key2; + } + +out: + if (res != TEE_SUCCESS) + cryp_state_free(sess->ctx, cs); + return res; +} + +TEE_Result tee_svc_cryp_state_copy(uint32_t dst, uint32_t src) +{ + TEE_Result res; + struct tee_cryp_state *cs_dst; + struct tee_cryp_state *cs_src; + struct tee_ta_session *sess; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_cryp_get_state(sess, dst, &cs_dst); + if (res != TEE_SUCCESS) + return res; + res = tee_svc_cryp_get_state(sess, src, &cs_src); + if (res != TEE_SUCCESS) + return res; + if (cs_dst->algo != cs_src->algo || cs_dst->mode != cs_src->mode) + return TEE_ERROR_BAD_PARAMETERS; + /* "Can't happen" */ + if (cs_dst->ctx_size != cs_src->ctx_size) + return TEE_ERROR_BAD_STATE; + + memcpy(cs_dst->ctx, cs_src->ctx, cs_src->ctx_size); + return TEE_SUCCESS; +} + +void tee_svc_cryp_free_states(struct tee_ta_ctx *ctx) +{ + struct tee_cryp_state_head *states = &ctx->cryp_states; + + while (!TAILQ_EMPTY(states)) + cryp_state_free(ctx, TAILQ_FIRST(states)); +} + +TEE_Result tee_svc_cryp_state_free(uint32_t state) +{ + TEE_Result res; + struct tee_cryp_state *cs; + struct tee_ta_session *sess; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_cryp_get_state(sess, state, &cs); + if (res != TEE_SUCCESS) + return res; + cryp_state_free(sess->ctx, cs); + return TEE_SUCCESS; +} + +/* iv and iv_len are ignored for some algorithms */ +TEE_Result tee_svc_hash_init(uint32_t state, const void *iv, size_t iv_len) +{ + TEE_Result res; + struct tee_cryp_state *cs; + struct tee_ta_session *sess; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_cryp_get_state(sess, state, &cs); + if (res != TEE_SUCCESS) + return res; + + switch (TEE_ALG_GET_CLASS(cs->algo)) { + case TEE_OPERATION_DIGEST: + res = tee_hash_init(cs->ctx, cs->algo); + if (res != TEE_SUCCESS) + return res; + break; + case TEE_OPERATION_MAC: + { + struct tee_obj *o; + struct tee_cryp_obj_secret *key; + + res = tee_obj_get(sess->ctx, cs->key1, &o); + if (res != TEE_SUCCESS) + return res; + if ((o->info.handleFlags & + TEE_HANDLE_FLAG_INITIALIZED) == 0) + return TEE_ERROR_BAD_PARAMETERS; + + key = (struct tee_cryp_obj_secret *)o->data; + res = tee_mac_init(cs->ctx, cs->algo, (void *)(key + 1), + key->key_size); + if (res != TEE_SUCCESS) + return res; + break; + } + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + return TEE_SUCCESS; +} + +TEE_Result tee_svc_hash_update(uint32_t state, const void *chunk, + size_t chunk_size) +{ + TEE_Result res; + struct tee_cryp_state *cs; + struct tee_ta_session *sess; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t)chunk, chunk_size); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_cryp_get_state(sess, state, &cs); + if (res != TEE_SUCCESS) + return res; + + switch (TEE_ALG_GET_CLASS(cs->algo)) { + case TEE_OPERATION_DIGEST: + res = tee_hash_update(cs->ctx, cs->algo, chunk, chunk_size); + if (res != TEE_SUCCESS) + return res; + break; + case TEE_OPERATION_MAC: + res = tee_mac_update(cs->ctx, cs->algo, chunk, chunk_size); + if (res != TEE_SUCCESS) + return res; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + return TEE_SUCCESS; +} + +TEE_Result tee_svc_hash_final(uint32_t state, const void *chunk, + size_t chunk_size, void *hash, size_t *hash_len) +{ + TEE_Result res, res2; + size_t hash_size; + size_t hlen; + struct tee_cryp_state *cs; + struct tee_ta_session *sess; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t)chunk, chunk_size); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_copy_from_user(sess, &hlen, hash_len, sizeof(size_t)); + if (res != TEE_SUCCESS) + return res; + + res = tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t)hash, hlen); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_cryp_get_state(sess, state, &cs); + if (res != TEE_SUCCESS) + return res; + + switch (TEE_ALG_GET_CLASS(cs->algo)) { + case TEE_OPERATION_DIGEST: + res = tee_hash_get_digest_size(cs->algo, &hash_size); + if (res != TEE_SUCCESS) + return res; + if (*hash_len < hash_size) { + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + res = tee_hash_update(cs->ctx, cs->algo, chunk, chunk_size); + if (res != TEE_SUCCESS) + return res; + res = tee_hash_final(cs->ctx, cs->algo, hash, hash_size); + if (res != TEE_SUCCESS) + return res; + break; + case TEE_OPERATION_MAC: + res = tee_mac_get_digest_size(cs->algo, &hash_size); + if (res != TEE_SUCCESS) + return res; + if (*hash_len < hash_size) { + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + res = tee_mac_final(cs->ctx, cs->algo, chunk, chunk_size, hash, + hash_size); + if (res != TEE_SUCCESS) + return res; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } +out: + res2 = + tee_svc_copy_to_user(sess, hash_len, &hash_size, sizeof(*hash_len)); + if (res2 != TEE_SUCCESS) + return res2; + return res; +} + +TEE_Result tee_svc_cipher_init(uint32_t state, const void *iv, size_t iv_len) +{ + TEE_Result res; + struct tee_cryp_state *cs; + struct tee_ta_session *sess; + struct tee_obj *o; + struct tee_cryp_obj_secret *key1; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_cryp_get_state(sess, state, &cs); + if (res != TEE_SUCCESS) + return res; + + res = tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t) iv, iv_len); + if (res != TEE_SUCCESS) + return res; + + res = tee_obj_get(sess->ctx, cs->key1, &o); + if (res != TEE_SUCCESS) + return res; + if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) + return TEE_ERROR_BAD_PARAMETERS; + + key1 = (struct tee_cryp_obj_secret *)o->data; + + if (tee_obj_get(sess->ctx, cs->key2, &o) == TEE_SUCCESS) { + struct tee_cryp_obj_secret *key2 = + (struct tee_cryp_obj_secret *)o->data; + + if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_cipher_init3(cs->ctx, cs->algo, cs->mode, + (uint8_t *)(key1 + 1), key1->key_size, + (uint8_t *)(key2 + 1), key2->key_size, + iv, iv_len); + } else { + res = tee_cipher_init2(cs->ctx, cs->algo, cs->mode, + (uint8_t *)(key1 + 1), key1->key_size, + iv, iv_len); + } + if (res != TEE_SUCCESS) + return res; + + cs->ctx_finalize = (tee_cryp_ctx_finalize_func_t) tee_cipher_final; + return TEE_SUCCESS; +} + +static TEE_Result tee_svc_cipher_update_helper(uint32_t state, bool last_block, + const void *src, size_t src_len, + void *dst, size_t *dst_len) +{ + TEE_Result res; + struct tee_cryp_state *cs; + struct tee_ta_session *sess; + size_t dlen; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_cryp_get_state(sess, state, &cs); + if (res != TEE_SUCCESS) + return res; + + res = tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t)src, src_len); + if (res != TEE_SUCCESS) + return res; + + if (dst_len == NULL) { + dlen = 0; + } else { + res = + tee_svc_copy_from_user(sess, &dlen, dst_len, + sizeof(size_t)); + if (res != TEE_SUCCESS) + return res; + + res = tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t)dst, dlen); + if (res != TEE_SUCCESS) + return res; + } + + if (dlen < src_len) { + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + if (src_len > 0) { + /* Permit src_len == 0 to finalize the operation */ + res = tee_cipher_update(cs->ctx, cs->algo, cs->mode, last_block, + src, src_len, dst); + } + + if (last_block && cs->ctx_finalize != NULL) { + cs->ctx_finalize(cs->ctx, cs->mode); + cs->ctx_finalize = NULL; + } + +out: + if ((res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) && + dst_len != NULL) { + TEE_Result res2 = tee_svc_copy_to_user(sess, dst_len, &src_len, + sizeof(size_t)); + if (res2 != TEE_SUCCESS) + res = res2; + } + + return res; +} + +TEE_Result tee_svc_cipher_update(uint32_t state, const void *src, + size_t src_len, void *dst, size_t *dst_len) +{ + return tee_svc_cipher_update_helper(state, false /* last_block */, + src, src_len, dst, dst_len); +} + +TEE_Result tee_svc_cipher_final(uint32_t state, const void *src, + size_t src_len, void *dst, size_t *dst_len) +{ + return tee_svc_cipher_update_helper(state, true /* last_block */, + src, src_len, dst, dst_len); +} + +TEE_Result tee_svc_cryp_derive_key(uint32_t state, const TEE_Attribute *params, + uint32_t param_count, uint32_t derived_key) +{ + TEE_Result res; + struct tee_ta_session *sess; + struct tee_obj *ko; + struct tee_obj *so; + struct tee_cryp_state *cs; + struct tee_cryp_obj_secret *sk; + const struct tee_cryp_obj_type_props *type_props; + struct ltc_bignumbers publicvalue; + struct ltc_bignumbers sharedsecret; + struct tee_ltc_dh_key_pair *tee_dh_key; + dh_key ltc_dh_key; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_cryp_get_state(sess, state, &cs); + if (res != TEE_SUCCESS) + return res; + + if ((param_count != 1) || + (params[0].attributeID != TEE_ATTR_DH_PUBLIC_VALUE)) + return TEE_ERROR_BAD_PARAMETERS; + + /* get key set in operation */ + res = tee_obj_get(sess->ctx, cs->key1, &ko); + if (res != TEE_SUCCESS) + return res; + + tee_dh_key = (struct tee_ltc_dh_key_pair *)ko->data; + tee_populate_dh_key_pair(<c_dh_key, tee_dh_key); + + res = tee_obj_get(sess->ctx, derived_key, &so); + if (res != TEE_SUCCESS) + return res; + + /* find information needed about the object to initialize */ + sk = (struct tee_cryp_obj_secret *)so->data; + + /* Find description of object */ + type_props = tee_svc_find_type_props(so->info.objectType); + if (type_props == NULL) + return TEE_ERROR_NOT_SUPPORTED; + + SET_MPA_ALLOCSIZE(&publicvalue); + SET_MPA_ALLOCSIZE(&sharedsecret); + + /* extract information from the attributes passed to the function */ + mp_read_unsigned_bin( + &publicvalue, + params[0].content.ref.buffer, + params[0].content.ref.length); + res = tee_derive_dh_shared_secret( + <c_dh_key, &publicvalue, &sharedsecret); + + if (res == TEE_SUCCESS) { + sk->key_size = mp_unsigned_bin_size(&sharedsecret); + mp_to_unsigned_bin(&sharedsecret, (uint8_t *)(sk + 1)); + so->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; + SET_ATTRIBUTE(so, type_props, TEE_ATTR_SECRET_VALUE); + } + return res; +} + +TEE_Result get_rng_array(void *buffer, int len) +{ + char *buf_char = buffer; + int i; + + + if (buf_char == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + for (i = 0; i < len; i++) + buf_char[i] = hw_get_random_byte(); + + return TEE_SUCCESS; +} + +TEE_Result tee_svc_cryp_random_number_generate(void *buf, size_t blen) +{ + TEE_Result res; + struct tee_ta_session *sess; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t)buf, blen); + if (res != TEE_SUCCESS) + return res; + + res = get_rng_array(buf, blen); + if (res != TEE_SUCCESS) + return res; + + return res; +} + +TEE_Result tee_svc_authenc_init(uint32_t state, const void *nonce, + size_t nonce_len, size_t tag_len, + size_t aad_len, size_t payload_len) +{ + TEE_Result res; + struct tee_cryp_state *cs; + struct tee_ta_session *sess; + struct tee_obj *o; + struct tee_cryp_obj_secret *key; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_cryp_get_state(sess, state, &cs); + if (res != TEE_SUCCESS) + return res; + + res = tee_obj_get(sess->ctx, cs->key1, &o); + if (res != TEE_SUCCESS) + return res; + if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) + return TEE_ERROR_BAD_PARAMETERS; + + key = (struct tee_cryp_obj_secret *)o->data; + res = tee_authenc_init(cs->ctx, cs->algo, cs->mode, + (uint8_t *)(key + 1), key->key_size, + nonce, nonce_len, tag_len, aad_len, payload_len); + if (res != TEE_SUCCESS) + return res; + + cs->ctx_finalize = (tee_cryp_ctx_finalize_func_t)tee_authenc_final; + return TEE_SUCCESS; +} + +TEE_Result tee_svc_authenc_update_aad(uint32_t state, const void *aad_data, + size_t aad_data_len) +{ + TEE_Result res; + struct tee_cryp_state *cs; + struct tee_ta_session *sess; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t) aad_data, aad_data_len); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_cryp_get_state(sess, state, &cs); + if (res != TEE_SUCCESS) + return res; + + res = tee_authenc_update_aad(cs->ctx, cs->algo, cs->mode, aad_data, + aad_data_len); + if (res != TEE_SUCCESS) + return res; + + return TEE_SUCCESS; +} + +TEE_Result tee_svc_authenc_update_payload(uint32_t state, const void *src_data, + size_t src_len, void *dst_data, + size_t *dst_len) +{ + TEE_Result res; + struct tee_cryp_state *cs; + struct tee_ta_session *sess; + size_t dlen; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_cryp_get_state(sess, state, &cs); + if (res != TEE_SUCCESS) + return res; + + res = tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t) src_data, src_len); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_copy_from_user(sess, &dlen, dst_len, sizeof(size_t)); + if (res != TEE_SUCCESS) + return res; + + res = tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t)dst_data, dlen); + if (res != TEE_SUCCESS) + return res; + + if (dlen < src_len) { + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + res = tee_authenc_update_payload(cs->ctx, cs->algo, cs->mode, src_data, + src_len, dst_data); + +out: + if (res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) { + TEE_Result res2 = tee_svc_copy_to_user(sess, dst_len, &src_len, + sizeof(size_t)); + if (res2 != TEE_SUCCESS) + res = res2; + } + + return res; +} + +TEE_Result tee_svc_authenc_enc_final(uint32_t state, const void *src_data, + size_t src_len, void *dst_data, + size_t *dst_len, void *tag, + size_t *tag_len) +{ + TEE_Result res; + struct tee_cryp_state *cs; + struct tee_ta_session *sess; + size_t dlen; + size_t tlen; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_cryp_get_state(sess, state, &cs); + if (res != TEE_SUCCESS) + return res; + + if (cs->mode != TEE_MODE_ENCRYPT) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t)src_data, src_len); + if (res != TEE_SUCCESS) + return res; + + if (dst_len == NULL) { + dlen = 0; + } else { + res = + tee_svc_copy_from_user(sess, &dlen, dst_len, + sizeof(size_t)); + if (res != TEE_SUCCESS) + return res; + + res = tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t)dst_data, dlen); + if (res != TEE_SUCCESS) + return res; + } + + if (dlen < src_len) { + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + res = tee_svc_copy_from_user(sess, &tlen, tag_len, sizeof(size_t)); + if (res != TEE_SUCCESS) + return res; + + res = tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t)tag, tlen); + if (res != TEE_SUCCESS) + return res; + + res = tee_authenc_enc_final(cs->ctx, cs->algo, src_data, src_len, + dst_data, tag, &tlen); + +out: + if (res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) { + TEE_Result res2; + + if (dst_len != NULL) { + res2 = tee_svc_copy_to_user(sess, dst_len, &src_len, + sizeof(size_t)); + if (res2 != TEE_SUCCESS) + return res2; + } + + res2 = + tee_svc_copy_to_user(sess, tag_len, &tlen, sizeof(size_t)); + if (res2 != TEE_SUCCESS) + return res2; + } + + return res; +} + +TEE_Result tee_svc_authenc_dec_final(uint32_t state, const void *src_data, + size_t src_len, void *dst_data, + size_t *dst_len, const void *tag, + size_t tag_len) +{ + TEE_Result res; + struct tee_cryp_state *cs; + struct tee_ta_session *sess; + size_t dlen; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_cryp_get_state(sess, state, &cs); + if (res != TEE_SUCCESS) + return res; + + if (cs->mode != TEE_MODE_DECRYPT) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t)src_data, src_len); + if (res != TEE_SUCCESS) + return res; + + if (dst_len == NULL) { + dlen = 0; + } else { + res = + tee_svc_copy_from_user(sess, &dlen, dst_len, + sizeof(size_t)); + if (res != TEE_SUCCESS) + return res; + + res = tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t)dst_data, dlen); + if (res != TEE_SUCCESS) + return res; + } + + if (dlen < src_len) { + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + res = tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t)tag, tag_len); + if (res != TEE_SUCCESS) + return res; + + res = tee_authenc_dec_final(cs->ctx, cs->algo, src_data, src_len, + dst_data, tag, tag_len); + +out: + if ((res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) && + dst_len != NULL) { + TEE_Result res2; + + res2 = + tee_svc_copy_to_user(sess, dst_len, &src_len, + sizeof(size_t)); + if (res2 != TEE_SUCCESS) + return res2; + } + + return res; +} + +static void tee_svc_asymm_pkcs1_get_salt_len(const TEE_Attribute *params, + uint32_t num_params, int *salt_len) +{ + size_t n; + + for (n = 0; n < num_params; n++) { + if (params[n].attributeID == TEE_ATTR_RSA_PSS_SALT_LENGTH) { + *salt_len = params[n].content.value.a; + return; + } + } + *salt_len = -1; +} + +static TEE_Result tee_svc_asymm_rsa_check_crt_exist(struct tee_obj *o, + bool *crt_exist) +{ + const struct tee_cryp_obj_type_props *type_props; + int i; + + type_props = tee_svc_find_type_props(o->info.objectType); + if (type_props == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + /* + * if one crt attribute exits all must exists and this is + * checked when populating it + */ + i = tee_svc_cryp_obj_find_type_attr_idx(TEE_ATTR_RSA_PRIME1, + type_props); + + if ((o->have_attrs & (1 << i)) != 0) + *crt_exist = true; + else + *crt_exist = false; + + return TEE_SUCCESS; +} + +TEE_Result tee_svc_asymm_operate(uint32_t state, const TEE_Attribute *params, + uint32_t num_params, const void *src_data, + size_t src_len, void *dst_data, + size_t *dst_len) +{ + TEE_Result res; + struct tee_cryp_state *cs; + struct tee_ta_session *sess; + size_t dlen; + struct tee_obj *o; + struct tee_ltc_rsa_public_key *tee_rsa_public_key; + struct tee_ltc_rsa_key_pair *tee_rsa_key_pair; + struct tee_ltc_dsa_key_pair *tee_dsa_key; + union { + rsa_key ltc_rsa_key; + dsa_key ltc_dsa_key; + } key_type; + void *label = NULL; + size_t label_len = 0; + size_t n; + bool crt_exist; + int salt_len; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_cryp_get_state(sess, state, &cs); + if (res != TEE_SUCCESS) + return res; + + res = tee_mmu_check_access_rights( + sess->ctx, + TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t) src_data, src_len); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_copy_from_user(sess, &dlen, dst_len, sizeof(size_t)); + if (res != TEE_SUCCESS) + return res; + + res = tee_mmu_check_access_rights( + sess->ctx, + TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t) dst_data, dlen); + if (res != TEE_SUCCESS) + return res; + + res = tee_obj_get(sess->ctx, cs->key1, &o); + if (res != TEE_SUCCESS) + return res; + if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) + return TEE_ERROR_BAD_PARAMETERS; + + switch (cs->algo) { + case TEE_ALG_RSA_NOPAD: + if (cs->mode == TEE_MODE_ENCRYPT) { + tee_rsa_public_key = o->data; + tee_populate_rsa_public_key( + &key_type.ltc_rsa_key, tee_rsa_public_key); + } else if (cs->mode == TEE_MODE_DECRYPT) { + tee_rsa_key_pair = o->data; + res = tee_svc_asymm_rsa_check_crt_exist(o, &crt_exist); + if (res != TEE_SUCCESS) + return res; + tee_populate_rsa_key_pair( + &key_type.ltc_rsa_key, tee_rsa_key_pair, + crt_exist); + + } else { + res = TEE_ERROR_BAD_PARAMETERS; + } + + res = tee_acipher_rsadorep( + &key_type.ltc_rsa_key, + src_data, src_len, dst_data, &dlen); + break; + + case TEE_ALG_RSAES_PKCS1_V1_5: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512: + for (n = 0; n < num_params; n++) { + if (params[n].attributeID == TEE_ATTR_RSA_OAEP_LABEL) { + label = params[n].content.ref.buffer; + label_len = params[n].content.ref.length; + break; + } + } + + if (cs->mode == TEE_MODE_ENCRYPT) { + tee_rsa_public_key = o->data; + tee_populate_rsa_public_key( + &key_type.ltc_rsa_key, tee_rsa_public_key); + res = tee_acipher_rsaes_encrypt( + cs->algo, &key_type.ltc_rsa_key, + label, label_len, + src_data, src_len, dst_data, &dlen); + } else if (cs->mode == TEE_MODE_DECRYPT) { + tee_rsa_key_pair = o->data; + res = tee_svc_asymm_rsa_check_crt_exist(o, &crt_exist); + if (res != TEE_SUCCESS) + return res; + + tee_populate_rsa_key_pair( + &key_type.ltc_rsa_key, + tee_rsa_key_pair, crt_exist); + res = tee_acipher_rsaes_decrypt( + cs->algo, &key_type.ltc_rsa_key, + label, label_len, + src_data, src_len, dst_data, &dlen); + } else { + res = TEE_ERROR_BAD_PARAMETERS; + } + break; + + case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: + if (cs->mode != TEE_MODE_SIGN) { + res = TEE_ERROR_BAD_PARAMETERS; + break; + } + tee_rsa_key_pair = o->data; + res = tee_svc_asymm_rsa_check_crt_exist(o, &crt_exist); + if (res != TEE_SUCCESS) + return res; + tee_populate_rsa_key_pair( + &key_type.ltc_rsa_key, tee_rsa_key_pair, crt_exist); + + tee_svc_asymm_pkcs1_get_salt_len(params, num_params, &salt_len); + + res = tee_acipher_rsassa_sign( + cs->algo, &key_type.ltc_rsa_key, salt_len, + src_data, src_len, dst_data, &dlen); + break; + + case TEE_ALG_DSA_SHA1: + tee_dsa_key = o->data; + tee_populate_dsa_key_pair(&key_type.ltc_dsa_key, tee_dsa_key); + res = tee_acipher_dsa_sign( + cs->algo, &key_type.ltc_dsa_key, + src_data, src_len, dst_data, &dlen); + break; + + default: + res = TEE_ERROR_BAD_PARAMETERS; + break; + } + + if (res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) { + TEE_Result res2; + + res2 = + tee_svc_copy_to_user(sess, dst_len, &dlen, sizeof(size_t)); + if (res2 != TEE_SUCCESS) + return res2; + } + + return res; +} + +TEE_Result tee_svc_asymm_verify(uint32_t state, const TEE_Attribute *params, + uint32_t num_params, const void *data, + size_t data_len, const void *sig, + size_t sig_len) +{ + TEE_Result res; + struct tee_cryp_state *cs; + struct tee_ta_session *sess; + struct tee_obj *o; + size_t hash_size; + struct tee_ltc_rsa_public_key *tee_rsa_key; + int salt_len; + struct tee_ltc_dsa_public_key *tee_dsa_key; + union { + rsa_key ltc_rsa_key; + dsa_key ltc_dsa_key; + } key_type; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_cryp_get_state(sess, state, &cs); + if (res != TEE_SUCCESS) + return res; + + if (cs->mode != TEE_MODE_VERIFY) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t)data, data_len); + if (res != TEE_SUCCESS) + return res; + + res = tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t)sig, sig_len); + if (res != TEE_SUCCESS) + return res; + + res = tee_obj_get(sess->ctx, cs->key1, &o); + if (res != TEE_SUCCESS) + return res; + if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_hash_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(cs->algo), + &hash_size); + if (res != TEE_SUCCESS) + return res; + + if (data_len != hash_size) + return TEE_ERROR_BAD_PARAMETERS; + + switch (TEE_ALG_GET_MAIN_ALG(cs->algo)) { + case TEE_MAIN_ALGO_RSA: + tee_rsa_key = o->data; + tee_svc_asymm_pkcs1_get_salt_len(params, num_params, &salt_len); + tee_populate_rsa_public_key(&key_type.ltc_rsa_key, tee_rsa_key); + res = tee_acipher_rsassa_verify( + cs->algo, &key_type.ltc_rsa_key, salt_len, + data, data_len, sig, sig_len); + break; + + case TEE_MAIN_ALGO_DSA: + tee_dsa_key = o->data; + tee_populate_dsa_public_key(&key_type.ltc_dsa_key, tee_dsa_key); + res = tee_acipher_dsa_verify( + cs->algo, &key_type.ltc_dsa_key, + data, data_len, sig, sig_len); + break; + + default: + res = TEE_ERROR_NOT_SUPPORTED; + } + + return res; +} diff --git a/core/tee/tee_svc_storage.c b/core/tee/tee_svc_storage.c new file mode 100644 index 00000000000..800acff4d44 --- /dev/null +++ b/core/tee/tee_svc_storage.c @@ -0,0 +1,1098 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* SSF (Secure Storage File version 00 */ +#define TEE_SVC_STORAGE_MAGIC 0x53534600; + +/* Header of GP formated secure storage files */ +struct tee_svc_storage_head { + uint32_t magic; + uint32_t head_size; + uint32_t meta_size; + uint32_t ds_size; +}; + +struct tee_storage_enum { + TAILQ_ENTRY(tee_storage_enum) link; + tee_fs_dir *dir; +}; + +static TEE_Result tee_svc_storage_get_enum(struct tee_ta_ctx *ctx, + uint32_t enum_id, + struct tee_storage_enum **e_out) +{ + struct tee_storage_enum *e; + + TAILQ_FOREACH(e, &ctx->storage_enums, link) { + if (enum_id == (uint32_t) e) { + *e_out = e; + return TEE_SUCCESS; + } + } + return TEE_ERROR_BAD_PARAMETERS; +} + +static TEE_Result tee_svc_close_enum(struct tee_ta_ctx *ctx, + struct tee_storage_enum *e) +{ + int ret; + + if (e == NULL || ctx == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + TAILQ_REMOVE(&ctx->storage_enums, e, link); + + ret = tee_fs_closedir(e->dir); + e->dir = NULL; + + free(e); + + if (ret != 0) + return TEE_ERROR_ITEM_NOT_FOUND; + + return TEE_SUCCESS; +} + +static char *tee_svc_storage_create_filename(struct tee_ta_session *sess, + void *object_id, + uint32_t object_id_len) +{ + uint8_t *file = NULL; + /* +1 for the '/' */ + uint32_t hslen = + TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID) + object_id_len) + 1; + uint32_t pos; + + file = malloc(hslen); + + if (file == NULL) + return NULL; + + pos = tee_b2hs((uint8_t *)&sess->ctx->head->uuid, file, + sizeof(TEE_UUID), hslen); + file[pos] = '/'; + pos++; + tee_b2hs(object_id, file + pos, object_id_len, hslen - pos); + + return (char *)file; +} + +static char *tee_svc_storage_create_dirname(struct tee_ta_session *sess) +{ + uint8_t *dir = NULL; + uint32_t hslen = TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID)); + + dir = malloc(hslen); + + if (dir == NULL) + return NULL; + + tee_b2hs((uint8_t *)&sess->ctx->head->uuid, dir, sizeof(TEE_UUID), + hslen); + + return (char *)dir; +} + +static uint32_t tee_svc_storage_conv_oflags(uint32_t flags) +{ + uint32_t out = 0; + + if (flags & (TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_SHARE_READ)) { + if (flags & (TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META | + TEE_DATA_FLAG_SHARE_WRITE)) + out |= TEE_FS_O_RDWR; + else + out |= TEE_FS_O_RDONLY; + } else { + if (flags & (TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META | + TEE_DATA_FLAG_SHARE_WRITE)) + out |= TEE_FS_O_WRONLY; + } + + if (flags & TEE_DATA_FLAG_EXCLUSIVE) + out |= TEE_FS_O_EXCL; + + return out; +} + +static int tee_svc_storage_conv_whence(TEE_Whence whence) +{ + switch (whence) { + case TEE_DATA_SEEK_SET: + return TEE_FS_SEEK_SET; + case TEE_DATA_SEEK_CUR: + return TEE_FS_SEEK_CUR; + case TEE_DATA_SEEK_END: + return TEE_FS_SEEK_END; + default: + return -1; + } +} + +static TEE_Result tee_svc_storage_create_file(struct tee_ta_session *sess, + char *file, int *fd, + uint32_t flags) +{ + TEE_Result res = TEE_SUCCESS; + char *dir = NULL; + int tmp; + uint32_t cflags = TEE_FS_O_WRONLY | TEE_FS_O_CREATE; + + if (flags & TEE_DATA_FLAG_EXCLUSIVE) + cflags |= TEE_FS_O_EXCL; + + *fd = tee_fs_open(file, cflags); + + if (*fd < 0) { + /* try and make directory */ + dir = tee_svc_storage_create_dirname(sess); + if (dir == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto exit; + } + + tmp = tee_fs_mkdir(dir, TEE_FS_S_IRUSR | TEE_FS_S_IWUSR); + free(dir); + + if (tmp < 0) { + /* error codes needs better granularity */ + res = TEE_ERROR_GENERIC; + goto exit; + } + + /* try and open again */ + *fd = tee_fs_open(file, cflags); + + if (*fd < 0) { + /* error codes needs better granularity */ + res = TEE_ERROR_GENERIC; + goto exit; + } + } + +exit: + return res; +} + +static TEE_Result tee_svc_storage_read_head(struct tee_ta_session *sess, + struct tee_obj *o) +{ + TEE_Result res = TEE_SUCCESS; + int fd = -1; + int err; + struct tee_svc_storage_head head; + char *file = NULL; + + if (o == NULL || o->pobj == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + file = + tee_svc_storage_create_filename(sess, o->pobj->obj_id, + o->pobj->obj_id_len); + if (file == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto exit; + } + + fd = tee_fs_open(file, TEE_FS_O_RDONLY); + free(file); + + /* error codes needs better granularity */ + if (fd < 0) + return TEE_ERROR_ITEM_NOT_FOUND; + + /* read head */ + err = tee_fs_read(fd, &head, sizeof(struct tee_svc_storage_head)); + if (err != sizeof(struct tee_svc_storage_head)) { + res = TEE_ERROR_BAD_FORMAT; + goto exit; + } + + o->data_size = head.meta_size; + o->info.dataSize = head.ds_size; + + o->data = malloc(o->data_size); + if (o->data == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto exit; + } + + /* read meta */ + err = tee_fs_read(fd, o->data, o->data_size); + if (err != (int)o->data_size) { + free(o->data); + o->data = NULL; + res = TEE_ERROR_NO_DATA; + } + +exit: + tee_fs_close(fd); + + return res; +} + +static TEE_Result tee_svc_storage_init_file(struct tee_ta_session *sess, + struct tee_obj *o, + struct tee_obj *attr_o, void *data, + uint32_t len, uint32_t flags) +{ + TEE_Result res = TEE_SUCCESS; + int fd; + int err; + struct tee_svc_storage_head head; + char *file = NULL; + + if (o == NULL || o->pobj == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + free(o->data); + + if (attr_o && attr_o->data_size) { + o->data_size = attr_o->data_size; + o->data = malloc(attr_o->data_size); + if (o->data == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + memcpy(o->data, attr_o->data, attr_o->data_size); + o->have_attrs = attr_o->have_attrs; + o->info.objectUsage = attr_o->info.objectUsage; + o->info.objectType = attr_o->info.objectType; + } else { + o->data = NULL; + o->data_size = 0; + o->have_attrs = 0; + o->info.objectUsage = TEE_USAGE_DEFAULT; + o->info.objectType = 0; + } + + /* write head */ + head.magic = TEE_SVC_STORAGE_MAGIC; + head.head_size = sizeof(struct tee_svc_storage_head); + head.meta_size = o->data_size; + head.ds_size = len; + + file = + tee_svc_storage_create_filename(sess, o->pobj->obj_id, + o->pobj->obj_id_len); + if (file == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + res = tee_svc_storage_create_file(sess, file, &fd, flags); + free(file); + if (res != TEE_SUCCESS) + return res; + + /* error codes needs better granularity */ + if (fd < 0) + return TEE_ERROR_GENERIC; + + /* write head */ + err = tee_fs_write(fd, &head, sizeof(struct tee_svc_storage_head)); + /* error codes needs better granularity */ + if (err != sizeof(struct tee_svc_storage_head)) { + res = TEE_ERROR_GENERIC; + goto exit; + } + + /* write meta */ + err = tee_fs_write(fd, o->data, o->data_size); + /* error codes needs better granularity */ + if (err != (int)o->data_size) { + res = TEE_ERROR_GENERIC; + goto exit; + } + + /* write init data */ + o->info.dataSize = len; + + /* write data to fs if needed */ + if (data && len) { + err = tee_fs_write(fd, data, len); + + if (err != (int)len) { + /* error codes needs better granularity */ + res = TEE_ERROR_GENERIC; + return res; + } + } + +exit: + tee_fs_close(fd); + + return TEE_SUCCESS; +} + +static TEE_Result tee_svc_storage_remove(struct tee_ta_session *sess, + uint32_t storage_id, void *object_id, + uint32_t object_id_len) +{ + TEE_Result res = TEE_SUCCESS; + char *file = NULL; + int err; + + if (sess == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + if (storage_id != TEE_STORAGE_PRIVATE) + return TEE_ERROR_ITEM_NOT_FOUND; + + file = tee_svc_storage_create_filename(sess, object_id, object_id_len); + if (file == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + err = tee_fs_unlink(file); + free(file); + if (err != 0) + /* error codes needs better granularity */ + res = TEE_ERROR_GENERIC; + + return res; +} + +TEE_Result tee_svc_storage_obj_open(uint32_t storage_id, void *object_id, + uint32_t object_id_len, uint32_t flags, + uint32_t *obj) +{ + TEE_Result res; + struct tee_ta_session *sess; + struct tee_obj *o; + char *file = NULL; + int fs_flags; + int fd = -1; + tee_fs_off_t off; + tee_fs_off_t e_off; + struct tee_pobj *po = NULL; + + if (storage_id != TEE_STORAGE_PRIVATE) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (object_id_len > TEE_OBJECT_ID_MAX_LEN) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + goto exit; + + res = + tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t) object_id, object_id_len); + if (res != TEE_SUCCESS) + goto exit; + + res = tee_pobj_get((void *)&sess->ctx->head->uuid, object_id, + object_id_len, flags, &po); + if (res != TEE_SUCCESS) + goto exit; + + fs_flags = tee_svc_storage_conv_oflags(flags); + + o = calloc(1, sizeof(*o)); + if (o == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto exit; + } + + o->info.handleFlags = + TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; + o->info.objectUsage = TEE_USAGE_DEFAULT; + o->flags = flags; + o->pobj = po; + + res = tee_svc_storage_read_head(sess, o); + if (res != TEE_SUCCESS) { + free(o); + goto exit; + } + + file = tee_svc_storage_create_filename(sess, object_id, object_id_len); + if (file == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto exit; + } + + fd = tee_fs_open(file, fs_flags); + free(file); + if (fd < 0) { + res = TEE_ERROR_ITEM_NOT_FOUND; + goto exit; + } + o->fd = fd; + + tee_obj_add(sess->ctx, o); + + res = tee_svc_copy_to_user(sess, obj, &o, sizeof(o)); + if (res != TEE_SUCCESS) + tee_obj_close(sess->ctx, o); + + e_off = sizeof(struct tee_svc_storage_head) + o->data_size; + off = tee_fs_lseek(fd, e_off, TEE_FS_SEEK_SET); + if (off != e_off) { + res = TEE_ERROR_NO_DATA; + goto exit; + } + +exit: + if (res != TEE_SUCCESS) { + if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) { + /* the file is corrupt, delete */ + tee_svc_storage_remove(sess, storage_id, object_id, + object_id_len); + + /* "greaceful" return */ + res = TEE_ERROR_ITEM_NOT_FOUND; + } + + if (fd >= 0) + tee_fs_close(fd); + if (po) + tee_pobj_release(po); + } + + return res; +} + +TEE_Result tee_svc_storage_obj_create(uint32_t storage_id, void *object_id, + uint32_t object_id_len, uint32_t flags, + uint32_t attr, void *data, uint32_t len, + uint32_t *obj) +{ + TEE_Result res; + struct tee_ta_session *sess; + struct tee_obj *o = NULL; + struct tee_obj *attr_o = NULL; + char *file = NULL; + int fd = -1; + int fs_flags; + tee_fs_off_t off; + tee_fs_off_t e_off; + struct tee_pobj *po = NULL; + + if (storage_id != TEE_STORAGE_PRIVATE) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (object_id_len > TEE_OBJECT_ID_MAX_LEN) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = + tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t) object_id, object_id_len); + if (res != TEE_SUCCESS) + goto exit; + + res = tee_pobj_get((void *)&sess->ctx->head->uuid, object_id, + object_id_len, flags, &po); + if (res != TEE_SUCCESS) + goto exit; + + /* Init attributes if attibutes are provided */ + if (attr != TEE_HANDLE_NULL) { + res = tee_obj_get(sess->ctx, attr, &attr_o); + if (res != TEE_SUCCESS) + goto exit; + } + + /* check rights of the provided buffer */ + if (data && len) { + res = + tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t) data, len); + + if (res != TEE_SUCCESS) + goto exit; + } + + o = calloc(1, sizeof(*o)); + if (o == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto exit; + } + + o->info.handleFlags = + TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; + o->flags = flags; + o->pobj = po; + + res = tee_svc_storage_init_file(sess, o, attr_o, data, len, flags); + if (res != TEE_SUCCESS) { + free(o); + goto exit; + } + + fs_flags = tee_svc_storage_conv_oflags(flags); + + file = tee_svc_storage_create_filename(sess, object_id, object_id_len); + if (file == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto exit; + } + + fd = tee_fs_open(file, fs_flags); + free(file); + file = NULL; + if (fd < 0) { + res = TEE_ERROR_ITEM_NOT_FOUND; + goto exit; + } + o->fd = fd; + + tee_obj_add(sess->ctx, o); + + res = tee_svc_copy_to_user(sess, obj, &o, sizeof(o)); + if (res != TEE_SUCCESS) + tee_obj_close(sess->ctx, o); + + e_off = sizeof(struct tee_svc_storage_head) + o->data_size; + off = tee_fs_lseek(fd, e_off, TEE_FS_SEEK_SET); + if (off != e_off) { + res = TEE_ERROR_NO_DATA; + goto exit; + } + +exit: + if (res != TEE_SUCCESS) { + if (fd >= 0) + tee_fs_close(fd); + if (po) + tee_pobj_release(po); + } + + return res; +} + +TEE_Result tee_svc_storage_obj_del(uint32_t obj) +{ + TEE_Result res; + struct tee_ta_session *sess; + struct tee_obj *o; + int err; + char *file; + char *dir; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_obj_get(sess->ctx, obj, &o); + if (res != TEE_SUCCESS) + return res; + + if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META)) + return TEE_ERROR_ACCESS_CONFLICT; + + if (o->pobj == NULL || o->pobj->obj_id == NULL) + return TEE_ERROR_BAD_STATE; + + file = + tee_svc_storage_create_filename(sess, o->pobj->obj_id, + o->pobj->obj_id_len); + if (file == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + tee_obj_close(sess->ctx, o); + + err = tee_fs_unlink(file); + free(file); + if (err != 0) + /* error codes needs better granularity */ + return TEE_ERROR_GENERIC; + + /* try and remove dir */ + dir = tee_svc_storage_create_dirname(sess); + if (dir == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + /* ignore result */ + tee_fs_rmdir(dir); + free(dir); + + return TEE_SUCCESS; +} + +TEE_Result tee_svc_storage_obj_rename(uint32_t obj, void *object_id, + uint32_t object_id_len) +{ + TEE_Result res; + struct tee_ta_session *sess; + struct tee_obj *o; + struct tee_pobj *po = NULL; + char *new_file = NULL; + char *old_file = NULL; + int err = -1; + + if (object_id_len > TEE_OBJECT_ID_MAX_LEN) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_obj_get(sess->ctx, obj, &o); + if (res != TEE_SUCCESS) + return res; + + if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META)) { + res = TEE_ERROR_BAD_STATE; + goto exit; + } + + if (o->pobj == NULL || o->pobj->obj_id == NULL) + return TEE_ERROR_BAD_STATE; + + res = + tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t) object_id, object_id_len); + if (res != TEE_SUCCESS) + goto exit; + + /* get new ds name */ + new_file = + tee_svc_storage_create_filename(sess, object_id, object_id_len); + if (new_file == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto exit; + } + + old_file = + tee_svc_storage_create_filename(sess, o->pobj->obj_id, + o->pobj->obj_id_len); + if (old_file == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto exit; + } + + /* reserve dest name */ + res = tee_pobj_get((void *)&sess->ctx->head->uuid, object_id, + object_id_len, TEE_DATA_FLAG_ACCESS_WRITE_META, &po); + if (res != TEE_SUCCESS) + goto exit; + + err = tee_fs_access(new_file, TEE_FS_F_OK); + if (err == 0) { + /* file exists */ + res = TEE_ERROR_ACCESS_CONFLICT; + goto exit; + } + + /* move */ + err = tee_fs_rename(old_file, new_file); + if (err) { + /* error codes needs better granularity */ + res = TEE_ERROR_GENERIC; + goto exit; + } + + res = tee_pobj_rename(o->pobj, object_id, object_id_len); + +exit: + tee_pobj_release(po); + + free(new_file); + free(old_file); + + return res; +} + +TEE_Result tee_svc_storage_alloc_enum(uint32_t *obj_enum) +{ + struct tee_storage_enum *e; + struct tee_ta_session *sess; + TEE_Result res; + + if (obj_enum == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + e = malloc(sizeof(struct tee_storage_enum)); + + if (e == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + e->dir = NULL; + TAILQ_INSERT_TAIL(&sess->ctx->storage_enums, e, link); + + return tee_svc_copy_to_user(sess, obj_enum, &e, + sizeof(TEE_ObjectEnumHandle *)); +} + +TEE_Result tee_svc_storage_free_enum(uint32_t obj_enum) +{ + struct tee_storage_enum *e; + TEE_Result res; + struct tee_ta_session *sess; + + if (obj_enum == TEE_HANDLE_NULL) + return TEE_SUCCESS; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_storage_get_enum(sess->ctx, obj_enum, &e); + if (res != TEE_SUCCESS) + return res; + + return tee_svc_close_enum(sess->ctx, e); +} + +TEE_Result tee_svc_storage_reset_enum(uint32_t obj_enum) +{ + struct tee_storage_enum *e; + int res; + struct tee_ta_session *sess; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + if (obj_enum == TEE_HANDLE_NULL) + return TEE_SUCCESS; + + res = tee_svc_storage_get_enum(sess->ctx, obj_enum, &e); + if (res != TEE_SUCCESS) + return res; + + res = tee_fs_closedir(e->dir); + e->dir = NULL; + if (res != 0) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +TEE_Result tee_svc_storage_start_enum(uint32_t obj_enum, uint32_t storage_id) +{ + struct tee_storage_enum *e; + char *dir; + TEE_Result res; + struct tee_ta_session *sess; + + if (obj_enum == TEE_HANDLE_NULL) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_storage_get_enum(sess->ctx, obj_enum, &e); + if (res != TEE_SUCCESS) + return res; + + if (storage_id != TEE_STORAGE_PRIVATE) + return TEE_ERROR_ITEM_NOT_FOUND; + + dir = tee_svc_storage_create_dirname(sess); + if (dir == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + e->dir = tee_fs_opendir(dir); + free(dir); + + if (e->dir == NULL) + /* error codes needs better granularity */ + return TEE_ERROR_ITEM_NOT_FOUND; + + return TEE_SUCCESS; +} + +TEE_Result tee_svc_storage_next_enum(uint32_t obj_enum, TEE_ObjectInfo *info, + void *obj_id, size_t *len) +{ + struct tee_storage_enum *e; + struct tee_fs_dirent *d; + TEE_Result res = TEE_SUCCESS; + struct tee_ta_session *sess; + struct tee_obj *o = NULL; + uint32_t blen; + uint32_t hslen; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + if (obj_enum == TEE_HANDLE_NULL) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_svc_storage_get_enum(sess->ctx, obj_enum, &e); + if (res != TEE_SUCCESS) + return res; + + /* check rights of the provided buffers */ + res = + tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t) info, + sizeof(TEE_ObjectInfo)); + if (res != TEE_SUCCESS) + return res; + + res = + tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t) obj_id, + TEE_OBJECT_ID_MAX_LEN); + if (res != TEE_SUCCESS) + return res; + + d = tee_fs_readdir(e->dir); + if (d == NULL) + return TEE_ERROR_ITEM_NOT_FOUND; + + o = calloc(1, sizeof(struct tee_obj)); + if (o == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto exit; + } + + o->pobj = calloc(1, sizeof(struct tee_pobj)); + if (!o->pobj) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto exit; + } + + o->info.handleFlags = + TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; + o->info.objectUsage = TEE_USAGE_DEFAULT; + + /* + * NOTE: Special usage of pobj due to not ref cnt should be inc + */ + hslen = strlen(d->d_name); + blen = TEE_HS2B_BBUF_SIZE(hslen); + o->pobj->obj_id = malloc(blen); + if (o->pobj->obj_id == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto exit; + } + tee_hs2b((uint8_t *)d->d_name, o->pobj->obj_id, hslen, blen); + o->pobj->obj_id_len = blen; + + res = tee_svc_storage_read_head(sess, o); + if (res != TEE_SUCCESS) { + /* TODO: handle corrupt files in a greaceful way */ + goto exit; + } + memcpy(info, &o->info, sizeof(TEE_ObjectInfo)); + memcpy(obj_id, o->pobj->obj_id, o->pobj->obj_id_len); + + res = + tee_svc_copy_to_user(sess, len, &o->pobj->obj_id_len, + sizeof(uint32_t)); + +exit: + if (o) { + if (o->pobj) + free(o->pobj->obj_id); + free(o->pobj); + free(o->data); + } + free(o); + + return res; +} + +TEE_Result tee_svc_storage_obj_read(uint32_t obj, void *data, size_t len, + uint32_t *count) +{ + TEE_Result res; + struct tee_ta_session *sess; + struct tee_obj *o; + int n_count; + uint32_t u_count; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_obj_get(sess->ctx, obj, &o); + if (res != TEE_SUCCESS) + return res; + + if (!(o->flags & TEE_DATA_FLAG_ACCESS_READ)) + return TEE_ERROR_ACCESS_CONFLICT; + + /* check rights of the provided buffer */ + res = + tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t) data, len); + if (res != TEE_SUCCESS) + return res; + + n_count = tee_fs_read(o->fd, data, len); + u_count = (uint32_t) ((n_count < 0) ? 0 : n_count); + + res = tee_svc_copy_to_user(sess, count, &u_count, sizeof(uint32_t)); + + o->info.dataPosition += u_count; + + return TEE_SUCCESS; +} + +TEE_Result tee_svc_storage_obj_write(uint32_t obj, void *data, size_t len) +{ + TEE_Result res; + struct tee_ta_session *sess; + struct tee_obj *o; + int err; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_obj_get(sess->ctx, obj, &o); + if (res != TEE_SUCCESS) + return res; + + if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE)) + return TEE_ERROR_ACCESS_CONFLICT; + + /* check rights of the provided buffer */ + res = + tee_mmu_check_access_rights(sess->ctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (tee_uaddr_t) data, len); + + err = tee_fs_write(o->fd, data, len); + + if (err != (int)len) { + /* error codes needs better granularity */ + res = TEE_ERROR_GENERIC; + return res; + } + + o->info.dataPosition += len; + if (o->info.dataPosition > o->info.dataSize) + o->info.dataSize = o->info.dataPosition; + + return TEE_SUCCESS; +} + +TEE_Result tee_svc_storage_obj_trunc(uint32_t obj, size_t len) +{ + TEE_Result res; + struct tee_ta_session *sess; + struct tee_obj *o; + int err; + tee_fs_off_t off; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_obj_get(sess->ctx, obj, &o); + if (res != TEE_SUCCESS) + return res; + + if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE)) + return TEE_ERROR_ACCESS_CONFLICT; + + off = sizeof(struct tee_svc_storage_head) + o->data_size; + err = tee_fs_ftruncate(o->fd, len + off); + + if (err != 0) + /* error codes needs better granularity */ + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +TEE_Result tee_svc_storage_obj_seek(uint32_t obj, int32_t offset, + TEE_Whence whence) +{ + TEE_Result res; + struct tee_ta_session *sess; + struct tee_obj *o; + int fw; + tee_fs_off_t off; + tee_fs_off_t e_off = 0; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_obj_get(sess->ctx, obj, &o); + if (res != TEE_SUCCESS) + return res; + + if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) + return TEE_ERROR_BAD_STATE; + + fw = tee_svc_storage_conv_whence(whence); + + if (whence == TEE_DATA_SEEK_SET) + e_off = sizeof(struct tee_svc_storage_head) + o->data_size; + + off = tee_fs_lseek(o->fd, e_off + offset, fw); + if (off > -1 && off >= e_off) + o->info.dataPosition = + off - sizeof(struct tee_svc_storage_head) + o->data_size; + else + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +void tee_svc_storage_close_all_enum(struct tee_ta_ctx *ctx) +{ + struct tee_storage_enum_head *eh = &ctx->storage_enums; + + /* disregard return value */ + while (!TAILQ_EMPTY(eh)) + tee_svc_close_enum(ctx, TAILQ_FIRST(eh)); +} diff --git a/core/tee/tee_time_generic.c b/core/tee/tee_time_generic.c new file mode 100644 index 00000000000..4e1d4110c67 --- /dev/null +++ b/core/tee/tee_time_generic.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * tee_time_get_ree_time(): this function implements the GP Internal API + * function TEE_GetREETime() + * Goal is to get the time of the Rich Execution Environment + * This is why this time is provided through the supplicant + */ +TEE_Result tee_time_get_ree_time(TEE_Time *time) +{ + TEE_Result res = TEE_ERROR_BAD_PARAMETERS; + struct teesmc32_arg *arg; + struct teesmc32_param *params; + paddr_t pharg = 0; + paddr_t phpayload = 0; + paddr_t cookie = 0; + TEE_Time *payload; + + if (!time) + goto exit; + + pharg = thread_rpc_alloc_arg(TEESMC32_GET_ARG_SIZE(1)); + if (!pharg) + goto exit; + thread_st_rpc_alloc_payload(sizeof(TEE_Time), &phpayload, &cookie); + if (!phpayload) + goto exit; + + if (!TEE_ALIGNMENT_IS_OK(pharg, struct teesmc32_arg) || + !TEE_ALIGNMENT_IS_OK(phpayload, TEE_Time)) + goto exit; + + if (core_pa2va(pharg, (uint32_t *)&arg) || + core_pa2va(phpayload, (uint32_t *)&payload)) + goto exit; + + arg->cmd = TEE_RPC_GET_TIME; + arg->ret = TEE_ERROR_GENERIC; + arg->num_params = 1; + params = TEESMC32_GET_PARAMS(arg); + params[0].attr = TEESMC_ATTR_TYPE_MEMREF_OUTPUT | + (TEESMC_ATTR_CACHE_I_WRITE_THR | + TEESMC_ATTR_CACHE_O_WRITE_THR) << + TEESMC_ATTR_CACHE_SHIFT; + params[0].u.memref.buf_ptr = phpayload; + params[0].u.memref.size = sizeof(TEE_Time); + + thread_rpc_cmd(pharg); + res = arg->ret; + if (res != TEE_SUCCESS) + goto exit; + + *time = *payload; + +exit: + thread_rpc_free_arg(pharg); + thread_st_rpc_free_payload(cookie); + return res; +} + +struct tee_ta_time_offs { + TEE_UUID uuid; + TEE_Time offs; + bool positive; +}; + +static struct tee_ta_time_offs *tee_time_offs; +static size_t tee_time_num_offs; + +static TEE_Result tee_time_ta_get_offs(const TEE_UUID *uuid, + const TEE_Time **offs, bool *positive) +{ + size_t n; + + for (n = 0; n < tee_time_num_offs; n++) { + if (memcmp(uuid, &tee_time_offs[n].uuid, sizeof(TEE_UUID)) + == 0) { + *offs = &tee_time_offs[n].offs; + *positive = tee_time_offs[n].positive; + return TEE_SUCCESS; + } + } + return TEE_ERROR_TIME_NOT_SET; +} + +static TEE_Result tee_time_ta_set_offs(const TEE_UUID *uuid, + const TEE_Time *offs, bool positive) +{ + size_t n; + struct tee_ta_time_offs *o; + + for (n = 0; n < tee_time_num_offs; n++) { + if (memcmp(uuid, &tee_time_offs[n].uuid, sizeof(TEE_UUID)) + == 0) { + tee_time_offs[n].offs = *offs; + tee_time_offs[n].positive = positive; + return TEE_SUCCESS; + } + } + + n = tee_time_num_offs + 1; + o = malloc(n * sizeof(struct tee_ta_time_offs)); + if (o == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + memcpy(o, tee_time_offs, + tee_time_num_offs * sizeof(struct tee_ta_time_offs)); + free(tee_time_offs); + tee_time_offs = o; + tee_time_offs[tee_time_num_offs].uuid = *uuid; + tee_time_offs[tee_time_num_offs].offs = *offs; + tee_time_offs[tee_time_num_offs].positive = positive; + tee_time_num_offs = n; + return TEE_SUCCESS; +} + +TEE_Result tee_time_get_ta_time(const TEE_UUID *uuid, TEE_Time *time) +{ + TEE_Result res; + const TEE_Time *offs; + bool positive; + TEE_Time t; + TEE_Time t2; + + res = tee_time_ta_get_offs(uuid, &offs, &positive); + if (res != TEE_SUCCESS) + return res; + + res = tee_time_get_sys_time(&t); + if (res != TEE_SUCCESS) + return res; + + if (positive) { + TEE_TIME_ADD(t, *offs, t2); + + /* Detect wrapping, the wrapped time should be returned. */ + if (TEE_TIME_LT(t2, t)) + res = TEE_ERROR_OVERFLOW; + } else { + TEE_TIME_SUB(t, *offs, t2); + + /* Detect wrapping, the wrapped time should be returned. */ + if (TEE_TIME_LE(t, t2)) + res = TEE_ERROR_OVERFLOW; + } + *time = t2; + + return res; +} + +TEE_Result tee_time_set_ta_time(const TEE_UUID *uuid, const TEE_Time *time) +{ + TEE_Result res; + TEE_Time offs; + TEE_Time t; + + /* Check that time is normalized. */ + if (time->millis >= TEE_TIME_MILLIS_BASE) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_time_get_sys_time(&t); + if (res != TEE_SUCCESS) + return res; + + if (TEE_TIME_LT(t, *time)) { + TEE_TIME_SUB(*time, t, offs); + return tee_time_ta_set_offs(uuid, &offs, true); + } else { + TEE_TIME_SUB(t, *time, offs); + return tee_time_ta_set_offs(uuid, &offs, false); + } +} diff --git a/documentation/build_system.md b/documentation/build_system.md new file mode 100644 index 00000000000..04a1133d828 --- /dev/null +++ b/documentation/build_system.md @@ -0,0 +1,28 @@ +# Build system + +The build system consists of a Makefile in the root of the git together +with sub.mk in all source directories and some supporting files: + +Name | Description +:----|:----------- +/Makefile | Top makefile +/core/core.mk | Submodule included from /Makefile and includes all makefiles needed to build TEE Core +/ta/ta.mk | Submodule included from /Makefile and includes all makefiles needed to create the TA devkit +/mk/compile.mk | Creates rules to make object files from source files +/mk/subdir.mk | Includes sub.mk recursively +/mk/lib.mk | Creates rules to make a library +/mk/cleanvars.mk | Cleans variables used by a submodule before a new submodule can be included + +## /Makefile + + +## /mk/compile.mk +Generates explicit rules for all source files given in "srcs". Each source +file can have specific compiler flags from "{c,a,cpp}flags_$(ofile)" where +"$(ofile)" is the object file generated from the source file. Compiler +flags can also be removed by "{c,a,cpp}flags_remove_$(ofile)". + +The object files are stored in the same hierachy as the source file but +with under "$(out-dir)$(base-prefix)", where "$(out-dir)" defaults to "out" +and "$(base-prefix)" is added to avoid conflicts for modules which are used +several times diff --git a/documentation/file_structure.md b/documentation/file_structure.md new file mode 100644 index 00000000000..4f33c1eed18 --- /dev/null +++ b/documentation/file_structure.md @@ -0,0 +1,60 @@ +# Structure of files + +## Top level directories +Directory | Description +:---------|:------------ +/core | Files that are only used building TEE Core +/lib | Files that are used both when building TEE Core and TAs +/ta | Files that are only used when building TAs +/mk | Makefiles supporting the build system +/tmp-stuff| Temporary stuff that will be removed before the final commit is made +/scripts | Helper scripts for miscellaneous tasks +/out | Created when building unless a different out directory is specified with O=... on the command line + +## Structure of /core +Directory | Description +:---------|:------------ +/arch | Architecture and platform specific files +/lib | Generic libraries that are likely to be replaced in a final product +/mm | Generic memory management, currently empty +/tee | Generic TEE files + +## Structure of /core/arch +Directory | Description +:---------|:------------ +/arm32 | ARMv7 and Aarch32 specific architecture and platform specific files +/user_mode| Linux used space specific files when debugging TEE Core as a user space process, only used for some development + +## Structure of /core/arch/arm32 +Directory | Description +:---------|:------------ +/include | Include files used in rest of TEE core but not in any supporting libraries +/kern | Low level and core parts of TEE Core +/mm | Memory management +/tee | TEE files +/sm | Secure Monitor +/plat-orly| Specific files for the Orly platform + +## Structure of /core/arch/arm32/include +Directory | Description +:---------|:------------ +/kern | Include files exposing API for /core/arch/arm32/kern files +/kta | Include files exposing the KTA API that is mainly used by kernel TAs +/mm | Include files exposing API for /core/arch/arm32/mm files +/rom | Old ROM files that should be removed before going public +/sm | Include files exposing API for Secure Monitor + +## Structure of /core/lib/lib{crypto,sla} +Directory | Description +:---------|:------------ +/ | Source files for the library +/include | Include files exposing the API of the library + +## Structure of /lib/libutils +Directory | Description +:---------|:------------ +/ | Source file for the library +/arch | Architecture specific source files +/arch/arm32 | ARMv7 and Aarch32 specific source files +/arch/arm32/include | ARMv7 and Aarch32 specific include files +/include | Include files exposing the API of the library diff --git a/lib/libmpa/arch/arm32/sub.mk b/lib/libmpa/arch/arm32/sub.mk new file mode 100644 index 00000000000..2f6ac41e8bf --- /dev/null +++ b/lib/libmpa/arch/arm32/sub.mk @@ -0,0 +1 @@ +srcs-y += mpa_arm_asm.s diff --git a/lib/libmpa/include/mpa.h b/lib/libmpa/include/mpa.h new file mode 100644 index 00000000000..5cd21c19a6f --- /dev/null +++ b/lib/libmpa/include/mpa.h @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef GUARD_MPA_H +#define GUARD_MPA_H + +#include "mpalib.h" + +/************************************************************************\ + * MACRO DEFINITIONS +\************************************************************************/ + +#define WORD_SIZE MPA_WORD_SIZE +#define BYTES_PER_WORD (MPA_WORD_SIZE >> 3) +#define NIBBLES_PER_WORD (MPA_WORD_SIZE >> 2) +#define LOG_OF_WORD_SIZE MPA_LOG_OF_WORD_SIZE +#define LOG_OF_BYTES_PER_WORD MPA_LOG_OF_BYTES_PER_WORD +#define WORD_ALL_BITS_ONE ((mpa_word_t)-1) + +/* number of bytes to hold x bits, x must be positive integer */ +#define BITS_TO_BYTES(x) (((x)+7) >> 3) +/* convert from bytes to bits */ +#define BYTES_TO_BITS(x) ((x) << 3) + +/* convert from words to bytes */ +#define WORDS_TO_BYTES(x) ((x) << LOG_OF_BYTES_PER_WORD) +/* convert from bytes to minimum number of words needed to hold x bytes */ +#define BYTES_TO_WORDS(x) (((x) + BYTES_PER_WORD - 1) >> LOG_OF_BYTES_PER_WORD) + +/* convert from bits to words and vice versa */ +#define WORDS_TO_BITS(x) ((x) * MPA_WORD_SIZE) +#define BITS_TO_WORDS(x) (((x) + MPA_WORD_SIZE - 1) / MPA_WORD_SIZE) + +#define __MAX(a, b) ((a) < (b) ? (b) : (a)) +#define __MIN(a, b) ((a) < (b) ? (a) : (b)) + +/* macros to access internal variables in a mpa_numbase */ + +#define MPA_NEG_SIGN -1 +#define MPA_POS_SIGN 1 + +#define __mpanum_alloced(x) ((x)->alloc) +#define __mpanum_size(x) ((mpa_usize_t)((x)->size >= 0 ? \ + (x)->size : -(x)->size)) +#define __mpanum_sign(x) ((x)->size >= 0 ? MPA_POS_SIGN : MPA_NEG_SIGN) + +/* macros to set internal variables in mpa_numbase */ + +/* SetSign take either MPA_POS_SIGN or MPA_NEG_SIGN as argument */ +#define __mpanum_set_sign(x, s) \ + do { \ + if (__mpanum_sign(x) != (s)) \ + (x)->size = -(x)->size; \ + } while (0) +#define __mpanum_is_zero(x) ((x)->size == 0) +#define __mpanum_neg(x) ((x)->size = -((x)->size)) + +/* Get most significant word of x, call only on non-zero x */ +#define __mpanum_msw(x) ((x)->d[__mpanum_size(x)-1]) +#define __mpanum_lsw(x) ((x)->d[0]) + +/* Get word idx of x, if idx >= size, return 0 + * This macro is used in the montgomery multiplication to allow + * operands to have shorter alloc than n + */ +#define __mpanum_get_word(idx, x) ((idx >= __mpanum_size(x)) ? \ + 0 : ((x)->d[idx])) + +/* n = 0..NIBBLES_PER_WORD-1 */ +#if defined(MPA_LITTLE_ENDIAN) +#define NIBBLE_OF_WORD(n, w) (((w) >> ((n) << 2)) & 0xf) +#elif defined(MPA_BIG_ENDIAN) +#define NIBBLE_OF_WORD(n, w) (((w) >> ((7-(n)) << 2)) & 0xf) +#else +#error "You must define either MPA_LITTLE_ENDIAN or MPA_BIG_ENDIAN, see mpalib_config.h" +#endif + +/* In order to avoid warnings on unused arguments */ +#ifndef IDENTIFIER_NOT_USED +#define IDENTIFIER_NOT_USED(x) (void)(&x) +#endif + +/* + * Is NULL defined? + */ +#if !defined(NULL) +#define NULL (void *)0 +#endif + +/* + * Always turn on debug print-outs if DEBUG is defined + * You can disable DPRINTS for each .c-file by + * #undef DEBUG_ME before the #include "mpa_debug.h" + */ +#if defined(DEBUG) +#define DEBUG_ME +#endif + +#if defined(DEBUG) + +#define MEMPOOL_MARKER(x) \ + uint32_t mpa_mempool_marker = __mpa_get_alloced_pattern((x)); +#define MEMPOOL_SANITY_CHECK(x) \ + do { \ + if (mpa_mempool_marker != __mpa_get_alloced_pattern((x))) { \ + DPRINT("MemPool is leaking!\n"); \ + } \ + } while (0) + +#else + +#define MEMPOOL_MARKER(x) +#define MEMPOOL_SANITY_CHECK(x) + +#endif + +/************************************************************* + * + * GLOBAL CONSTANTS AND VARIABLES + * + *************************************************************/ + +/* + * defined in mpa_misc.c + */ +extern const mpa_num_base const_largest_deci_base; +extern const mpa_num_base Const_1_LShift_Base; +extern const mpa_num_base const_one; + +/************************************************************* + * + * INTERNAL FUNCTIONS + * + *************************************************************/ + +/*------------------------------------------------------------ + * + * From mpa_mem_static. + * + */ +uint32_t __mpa_get_alloced_pattern(mpa_scratch_mem pool); + +/*------------------------------------------------------------ + * + * From mpa_addsub.c + * + */ +void __mpa_full_adder(mpa_word_t a, + mpa_word_t b, mpa_word_t *sum, mpa_word_t *carry); + +void __mpa_full_sub(mpa_word_t a, + mpa_word_t b, mpa_word_t *diff, mpa_word_t *carry); + +void __mpa_full_adder_ackum(mpa_word_t *d, mpa_word_t e, mpa_word_t *carry); + +void __mpa_abs_add(mpa_word_t *sum, + mpa_usize_t *sum_size, + const mpa_word_t *op1, + mpa_usize_t op1_size, + const mpa_word_t *op2, mpa_usize_t op2_size); + +void __mpa_abs_add_ackum(mpanum dest, const mpanum src); + +void __mpa_abs_sub(mpa_word_t *diff, + mpa_usize_t *diff_size, + const mpa_word_t *op1, + mpa_usize_t op1_size, + const mpa_word_t *op2, mpa_usize_t op2_size); + +/*------------------------------------------------------------ + * + * From mpa_cmp.c + * + */ + +int __mpa_abs_cmp(const mpanum op1, const mpanum op2); + +int __mpa_abs_greater_than(const mpanum op1, const mpanum op2); + +int __mpa_abs_less_than(const mpanum op1, const mpanum op2); + +/*------------------------------------------------------------ + * + * From mpa_mul.c + * + */ +void __mpa_mul_add_word(mpa_word_t a, + mpa_word_t b, mpa_word_t *p, mpa_word_t *carry); + +void __mpa_mul_add_word_cum(mpa_word_t a, + mpa_word_t b, mpa_word_t *p, mpa_word_t *carry); + +void __mpa_abs_mul_word(mpanum dest, const mpanum op1, mpa_word_t op2); + +void __mpa_abs_mul(mpanum dest, const mpanum op1, const mpanum op2); + +/*------------------------------------------------------------ + * + * From mpa_div.c + * + */ + +mpa_word_t __mpa_div_dword(mpa_word_t n0, + mpa_word_t n1, mpa_word_t d, mpa_word_t *r); + +void __mpa_div_q_r_internal_word(mpanum q, + mpanum r, + const mpanum op1, const mpa_word_t op2); + +void __mpa_div_q_r(mpanum q, + mpanum r, + const mpanum op1, const mpanum op2, mpa_scratch_mem pool); + +/*------------------------------------------------------------ + * + * From mpa_shift.c + * + */ + +void __mpa_shift_words_left(mpanum op, mpa_word_t q); +void __mpa_shift_words_right(mpanum op, mpa_word_t q); + +/*------------------------------------------------------------ + * + * From mpa_montgomery.c + * + */ + +void __mpa_montgomery_sub_ack(mpanum dest, mpanum src); + +void __mpa_montgomery_mul_add(mpanum dest, mpanum src, mpa_word_t w); + +void __mpa_montgomery_mul(mpanum dest, + mpanum op1, mpanum op2, mpanum n, mpa_word_t n_inv); + +/*------------------------------------------------------------ + * + * From mpa_misc.c + * + */ +void __mpa_set_unused_digits_to_zero(mpanum n); + +#endif /* include guard */ diff --git a/lib/libmpa/include/mpa_assert.h b/lib/libmpa/include/mpa_assert.h new file mode 100644 index 00000000000..1d4912096fd --- /dev/null +++ b/lib/libmpa/include/mpa_assert.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef GUARD_MPA_ASSERT_H +#define GUARD_MPA_ASSERT_H + +#include "mpa_debug.h" + +#if defined(DEBUG) + +#define ASSERT_DO(cond, str) \ + do { \ + if (!(cond)) { \ + __mpa_dbg_print_header(__func__, __LINE__); \ + __mpa_dbg_print("Assertion failed. Msg: %s\n", \ + (str)); \ + __mpa_dbg_print_header(__func__, __LINE__); \ + __mpa_dbg_print( \ + "Program will exit, waiting for keypress.\n"); \ + fflush(stdout); \ + getchar(); \ + exit(1); \ + } \ + } while (0) + +#define ASSERT(cond, str) ASSERT_DO(cond, str) + +#else + +#define ASSERT_DO(cond, str) \ + do { \ + if (!(cond)) { \ + while (1) \ + ; \ + } \ + } while (0) + +#define ASSERT(cond, str) ASSERT_DO(cond, str) +/* + * Must stop on assert + * #define ASSERT if (0) ((void (*)(const int cond, const char *str))(NULL)) + */ +#endif + +#endif /* include guard */ diff --git a/lib/libmpa/include/mpa_debug.h b/lib/libmpa/include/mpa_debug.h new file mode 100644 index 00000000000..7a23bd18356 --- /dev/null +++ b/lib/libmpa/include/mpa_debug.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef GUARD_MPA_DEBUG_H +#define GUARD_MPA_DEBUG_H + +#include "mpa.h" + +#if defined(DEBUG) + +#include +#include +#include + +/* console debug function declaration */ +void __mpa_dbg_print_stack(void); + +void __mpa_dbg_print_header(const char *f_str, const int l_num); +void __mpa_dbg_print(const char *format, ...); +void __mpa_dbg_print_mpanum_hexstr(const mpanum a); +void __mpa_dbg_dump_mpanum(const mpanum val); + +#endif /* defined (DEBUG) */ + +/* + * If DEBUG is defined we expand into a two-stage rocket and first print the + * calling function and the line, then print the debug message. + */ + +#if defined(DEBUG) && defined(DEBUG_ME) + +#define DPRINT_STACK __mpa_dbg_print_stack +#define DPRINT_WHERE \ + __mpa_dbg_print_header(__func__, __LINE__); + +#define DPRINT \ + DPRINT_WHERE \ + __mpa_dbg_print +#define DPRINT_MPANUM_HEXSTR(h, v, f) \ + do { \ + DPRINT_WHERE \ + __mpa_dbg_print("%s ", (h));\ + __mpa_dbg_print_mpanum_hexstr((v));\ + __mpa_dbg_print(" %s", (f)); + } while (0) +#define DPRINT_DUMP_MPANUM(h, v) \ + do { \ + DPRINT_WHERE\ + __mpa_dbg_print("%s ", (h));\ + __mpa_dbg_dump_mpanum((v)) + } while (0) + +#else /* !defined(DEBUG && DEBUG_ME) */ + +#define DPRINT_STACK \ + do { \ + if (0) \ + ((void (*)())(NULL)); \ + } while (0) + +#define DPRINT if (0) ((void (*)(const char*, ...))(NULL)) + +#define DPRINT_MPANUM_HEXSTR \ + do { \ + if (0) \ + ((void (*)(const char *h_str, const mpanum val, \ + const char *f_str))(NULL)) \ + } while (0) + +#define DPRINT_DUMP_MPANUM \ + do { \ + if (0) \ + ((void (*)(const char *h_str, \ + const mpanum val))(NULL)); \ + } while (0) +#endif /* !defined(DEBUG && DEBUG_ME) */ + +#endif /* include guard */ diff --git a/lib/libmpa/include/mpalib.h b/lib/libmpa/include/mpalib.h new file mode 100644 index 00000000000..93bfd04d89e --- /dev/null +++ b/lib/libmpa/include/mpalib.h @@ -0,0 +1,409 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef GUARD_MPALIB_H +#define GUARD_MPALIB_H + +/************************************************************* + * + * How functions are exported. + * + *************************************************************/ +#define MPALIB_EXPORT + +/************************************************************* + * + * Include common configuration definitions + * + *************************************************************/ +#include "mpalib_config.h" + +/************************************************************* + * + * TYPE DEFINITIONS + * + *************************************************************/ + +#if defined(MPA_SUPPORT_DWORD_T) +typedef unsigned long long mpa_dword_t; +#endif + +/*! \struct mpa_numbase_struct + * The internal representation of a multi precision integer. + * + * \param alloc The size of the allocated array d in number of mpa_word_t. + * + * \param size The number of used words in *d to represent the number, or + * minus the number if the mpa_numbase is representing a + * negative number. The mpa_numbase + * is representing zero if and only if size == 0. + * + * \param d The digits of the integer. The digits are in radix + * 2^WORD_SIZE. + * The digits are stored in a little endian format, i.e. + * the least significant word_t is stored in d[0]. + * + * \internal ** NOTE ** + * If you change this struct, you must update the const variables + * in mpa_misc.c and mpa_primetest.c + * And the + * MPA_NUMBASE_METADATA_SIZE_IN_U32 + * below. + */ +typedef struct mpa_numbase_struct { + mpa_asize_t alloc; + mpa_usize_t size; + mpa_word_t d[]; +} mpa_num_base; + +/*/ mpanum is the type we use as parameters to function calls in this library */ +typedef mpa_num_base *mpanum; + +/*! + * The Context struct for a Montgomery multiplication + * + * \internal ** NOTE ** + * If you change this struct, you must update the + * MPA_FMM_CONTEXT_METADATA_SIZE_IN_U32 + * below. + * + */ +typedef struct mpa_fmm_context_struct { + mpanum r_ptr; + mpanum r2_ptr; + mpa_word_t n_inv; + uint32_t m[]; +} mpa_fmm_context_base; + +typedef mpa_fmm_context_base *mpa_fmm_context; + +/* + * + * bit_size is the number of bits of the regular vars + * that this pool was created for. + */ +typedef struct mpa_scratch_mem_struct { + uint32_t nrof_vars; + uint32_t alloc_size; + uint32_t bit_size; + uint32_t m[]; +} mpa_scratch_mem_base; + +typedef mpa_scratch_mem_base *mpa_scratch_mem; + +/************************************************************* + * + * EXPORTED VARIABLES + * + *************************************************************/ + +/************************************************************* + * + * MACROS + * + *************************************************************/ + +#define MPA_STRING_MODE_HEX_UC 16 +#define MPA_STRING_MODE_HEX_LC 17 + +#define MPA_EVEN_PARITY 0 +#define MPA_ODD_PARITY 1 + +/*! Returns true if the mpanum 'a' is even (zero included) */ +#define mpa_is_even(a) (mpa_parity((a)) == MPA_EVEN_PARITY) +/*! Returns true if the mpanum 'a' is odd */ +#define mpa_is_odd(a) (mpa_parity((a)) == MPA_ODD_PARITY) +/* Short hand for setting the value of 'a' to the value of 'b' */ +#define mpa_set(a, b) mpa_copy((a), (b)) + +/* */ +/* Define how to convert between sizes given in uint32_t and mpa_word_t */ +/* */ +#define ASIZE_TO_U32(x) (((sizeof(mpa_word_t) * (x)) + 3) / 4) +#define U32_TO_ASIZE(x) \ + ((mpa_asize_t)(((4 * (x)) + (sizeof(mpa_word_t) - 1)) / \ + sizeof(mpa_word_t))) + +/************************************************************* + * + * STATIC MEMORY MODE DEFINES + * + *************************************************************/ + +/* + * The number of extra uint32_t in the internal representation. + * This is used in the static memory mode. + * It is chosen to be complient with the requirments of GlobalPlatform. + */ +#define MPA_NUMBASE_METADATA_SIZE_IN_U32 2 + +#define MPA_SCRATCHMEM_METADATA_SIZE_IN_U32 (sizeof(mpa_scratch_mem_base)/ 4) + +/* + * The size (in uint32_t) of the constituent variables + * of mpa_fmm_context apart from m[] + */ + +#define MPA_FMM_CONTEXT_METADATA_SIZE_IN_U32 (sizeof(mpa_fmm_context_base)/4) + +/* + * This macro returns the size of the complete mpa_num_base struct that + * can hold n-bits integers. This is used in the static memory mode. + */ +#define mpa_StaticVarSizeInU32(n) \ + ((((n)+31)/32) + MPA_NUMBASE_METADATA_SIZE_IN_U32) + +/* + * + */ +#define mpa_StaticTempVarSizeInU32(max_bits) \ + (2 * mpa_StaticVarSizeInU32((max_bits)) - \ + MPA_NUMBASE_METADATA_SIZE_IN_U32) + +/* + * + */ +#define mpa_scratch_mem_size_in_U32(nr_temp_vars, max_bits) \ + ((nr_temp_vars) * mpa_StaticTempVarSizeInU32(max_bits) + \ + MPA_SCRATCHMEM_METADATA_SIZE_IN_U32) + +/* + * + */ +#define mpa_fmm_context_size_in_U32(n) \ + (2 * (mpa_StaticVarSizeInU32((n)) + 2) + \ + MPA_FMM_CONTEXT_METADATA_SIZE_IN_U32) + +/************************************************************* + * + * FUNCTION PROTOTYPES + * + * All externally available functions from this lib. + * + *************************************************************/ + +/* + * From mpa_init.c + */ + +/* + * mpa_init_scratch_mem + * Initiate a chunk of memory to be used as a scratch pool. + * The size of the pool (in uint32_t) must corresponde to the + * size returned by the macro mpa_ScratchMemSizeInU32 + * with the same parameters 'nr_vars' and 'max_bits' + * + * \param pool The pool to initialize + * \param nr_vars The number of temp vars that it is sized to hold + * \param max_bits The maximum number of bits that the library + * can handle. + */ +MPALIB_EXPORT void mpa_init_scratch_mem(mpa_scratch_mem pool, + int nr_vars, int max_bits); + +/* + * mpa_init_static + * Initiate a mpanum to hold an integer of a certain size. + * The parameter 'len' is the return value of the macro + * mpa_StaticVarSizeInU32 called with the max bit size as parameter. + * + * \param src The mpanum to be initialized + * \param len The allocated size in uint32_t of src + */ +MPALIB_EXPORT void mpa_init_static(mpanum src, uint32_t len); + +MPALIB_EXPORT void mpa_init_static_fmm_context(mpa_fmm_context_base *context, + uint32_t len); + +/* + * From mpa_addsub.c + */ +MPALIB_EXPORT void mpa_add(mpanum dest, const mpanum op1, const mpanum op2, + mpa_scratch_mem pool); + +MPALIB_EXPORT void mpa_sub(mpanum dest, const mpanum op1, const mpanum op2, + mpa_scratch_mem pool); + +MPALIB_EXPORT void mpa_add_word(mpanum dest, const mpanum op1, mpa_word_t op2, + mpa_scratch_mem pool); + +MPALIB_EXPORT void mpa_sub_word(mpanum dest, const mpanum op1, mpa_word_t op2, + mpa_scratch_mem pool); + +MPALIB_EXPORT void mpa_neg(mpanum dest, const mpanum src); + +/* + * From mpa_mul.c + */ + +MPALIB_EXPORT void mpa_mul(mpanum dest, const mpanum op1, const mpanum op2, + mpa_scratch_mem pool); + +MPALIB_EXPORT void mpa_mul_word(mpanum dest, const mpanum op1, mpa_word_t op2, + mpa_scratch_mem pool); + +/* + * From mpa_div.c + */ + +MPALIB_EXPORT void mpa_div(mpanum q, mpanum r, + const mpanum op1, const mpanum op2, + mpa_scratch_mem pool); + +/* + * From mpa_modulus.c + */ + +MPALIB_EXPORT void mpa_mod(mpanum dest, const mpanum op, const mpanum n, + mpa_scratch_mem pool); + +MPALIB_EXPORT void mpa_add_mod(mpanum dest, const mpanum op1, const mpanum op2, + const mpanum n, mpa_scratch_mem pool); + +MPALIB_EXPORT void mpa_sub_mod(mpanum dest, const mpanum op1, const mpanum op2, + const mpanum n, mpa_scratch_mem pool); + +MPALIB_EXPORT void mpa_mul_mod(mpanum dest, const mpanum op1, const mpanum op2, + const mpanum n, mpa_scratch_mem pool); + +MPALIB_EXPORT int mpa_inv_mod(mpanum dest, const mpanum op, const mpanum n, + mpa_scratch_mem pool); + +/* + * From mpa_cmp.c + */ + +MPALIB_EXPORT int32_t mpa_cmp(const mpanum op1, const mpanum op2); + +MPALIB_EXPORT int32_t mpa_cmp_short(const mpanum op1, int32_t op2); + +/* + * From mpa_conv.c + */ + +MPALIB_EXPORT void mpa_set_S32(mpanum dest, int32_t short_val); + +MPALIB_EXPORT int32_t mpa_get_S32(int32_t *dest, mpanum src); + +MPALIB_EXPORT void mpa_set_word(mpanum dest, mpa_word_t src); + +MPALIB_EXPORT mpa_word_t mpa_get_word(mpanum src); + +/* + * From mpa_shift.c + */ + +MPALIB_EXPORT void mpa_shift_left(mpanum dest, const mpanum src, + mpa_word_t steps); + +MPALIB_EXPORT void mpa_shift_right(mpanum dest, const mpanum src, + mpa_word_t steps); + +/* + * From mpa_gcd.c + */ +MPALIB_EXPORT void mpa_gcd(mpanum dest, const mpanum src1, const mpanum src2, + mpa_scratch_mem pool); + +MPALIB_EXPORT void mpa_extended_gcd(mpanum gcd, mpanum dest1, mpanum dest2, + const mpanum src1, const mpanum src2, + mpa_scratch_mem pool); + +/* + * From mpa_io.c + */ +MPALIB_EXPORT int mpa_get_str_size(void); + +MPALIB_EXPORT int mpa_set_str(mpanum dest, const char *digitstr); + +MPALIB_EXPORT char *mpa_get_str(char *str, int mode, int groupsize, + const mpanum n); + +MPALIB_EXPORT int mpa_set_oct_str(mpanum dest, const uint8_t *buffer, + size_t buffer_len, bool negative); + +MPALIB_EXPORT int mpa_get_oct_str(uint8_t *buffer, size_t *buffer_len, + const mpanum n); + +/* + * From mpa_expmod.c + */ +MPALIB_EXPORT void mpa_exp_mod(mpanum dest, const mpanum op1, const mpanum op2, + const mpanum n, const mpanum r_modn, + const mpanum r2_modn, const mpa_word_t n_inv, + mpa_scratch_mem pool); + +/* + * From mpa_misc.c + */ + +MPALIB_EXPORT void mpa_wipe(mpanum src); + +MPALIB_EXPORT void mpa_copy(mpanum dest, const mpanum src); + +MPALIB_EXPORT void mpa_abs(mpanum dest, const mpanum src); + +MPALIB_EXPORT int mpa_highest_bit_index(const mpanum src); + +MPALIB_EXPORT uint32_t mpa_get_bit(const mpanum src, uint32_t idx); + +MPALIB_EXPORT int mpa_can_hold(mpanum dest, const mpanum src); + +MPALIB_EXPORT int mpa_parity(const mpanum src); + +MPALIB_EXPORT mpanum mpa_constant_one(void); + +/* + * From mpa_Random.c + */ +MPALIB_EXPORT void mpa_get_random(mpanum dest, mpanum limit); + +/* + * From mpa_montgomery.c + */ +MPALIB_EXPORT int mpa_compute_fmm_context(const mpanum modulus, mpanum r_modn, + mpanum r2_modn, mpa_word_t *n_inv, + mpa_scratch_mem pool); + +MPALIB_EXPORT void mpa_montgomery_mul(mpanum dest, mpanum op1, mpanum op2, + mpanum n, mpa_word_t n_inv, + mpa_scratch_mem pool); + +/* + * From mpa_mem_static.c + */ +MPALIB_EXPORT mpanum mpa_alloc_static_temp_var(mpanum *var, + mpa_scratch_mem pool); + +MPALIB_EXPORT void mpa_free_static_temp_var(mpanum *var, mpa_scratch_mem pool); + +/* + * From mpa_primetest.c + */ +MPALIB_EXPORT int mpa_is_prob_prime(mpanum n, int conf_level, + mpa_scratch_mem pool); + +#endif /* include guard */ diff --git a/lib/libmpa/include/mpalib_config.h b/lib/libmpa/include/mpalib_config.h new file mode 100644 index 00000000000..08ab5e0ac92 --- /dev/null +++ b/lib/libmpa/include/mpalib_config.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef GUARD_MPA_CONFIG_H +#define GUARD_MPA_CONFIG_H + +#include +#include +#include + +/************************************************************************\ + * Common definitions + * You should go through these carefully and adjust to your environment + \************************************************************************/ + +/* + * Definitions of different sized integers and unsigned + * + * mpa_word_t: should be an unsigned int of size equal to the most + * efficient add/sub/mul/div word size of the machine. + * + * mpa_int_t should be a signed int of the same size as the mpa_word_t + * + * mpa_halfw_t: half size of mpa_word_t + * + * mpa_asize_t: an unsigned int of suitable size to hold the number of + * allocated bytes for the representation. We cannot use size_t + * since that is 64 bit long on 64 bit machines, and that is + * ridiciously large. + * + * mpa_usize_t: a signed int suitable to hold the number of used mpa_word_t to + * represent the integer. + * + * mpa_byte_t: the native unsigned byte type. + */ +typedef uint32_t mpa_word_t; +typedef int32_t mpa_int_t; +typedef uint16_t mpa_halfw_t; +typedef uint32_t mpa_asize_t; +typedef int32_t mpa_usize_t; +typedef uint8_t mpa_byte_t; + +/* Number of bits in mpa_word_t */ +#define MPA_WORD_SIZE 32 + +/* Largest representable number in a mpa_int_t */ +#define MPA_INT_MAX INT32_MAX + +/* Smallest representable number in a mpa_int_t */ +#define MPA_INT_MIN INT32_MIN + +/* The Log2(MPA_WORD_SIZE) */ +#define MPA_LOG_OF_WORD_SIZE 5 + +/* The Log2 of number of bytes in a mpa_word_t */ +#define MPA_LOG_OF_BYTES_PER_WORD 2 + +/* The largest power of 10 representable in a mpa_word_t */ +#define LARGEST_DECIMAL_BASE_IN_WORD 1000000000 + +/* the number of decimal digits minus 1 in LARGEST_DECIMAL_BASE_IN_WORD */ +#define LARGEST_DECIMAL_BASE_DIGITS 9 + +/* The largest string size to represent a big number as a string */ +#define MPA_STR_MAX_SIZE (4096 + 2) + +/* define MPA_BIG_ENDIAN or MPA_LITTLE_ENDIAN */ +#define MPA_LITTLE_ENDIAN +/*#define MPA_BIG_ENDIAN */ + +/* + * comment out the line below if your system does not support "unsigned + * long long" + */ +#define MPA_SUPPORT_DWORD_T + +/* + * define if you want to use ARM assembler code for certain cruicial + * functions + */ +/* #define USE_ARM_ASM */ + +/* + * Include functionality for converting to and from strings; mpa_set_string + * and mpa_get_string. + */ +#define MPA_INCLUDE_STRING_CONVERSION + +/* + * Quick fix to be able to better define these mem functions later + */ +#define MACRO_DEF_MPA_MEMFUNCS + +#ifdef MACRO_DEF_MPA_MEMFUNCS +#include +#include +#define mpa_memset memset +#define mpa_memcpy memcpy +#define mpa_memmove memmove +#endif + +#endif /* include guard */ diff --git a/lib/libmpa/mpa_addsub.c b/lib/libmpa/mpa_addsub.c new file mode 100644 index 00000000000..d97c2e2ffbf --- /dev/null +++ b/lib/libmpa/mpa_addsub.c @@ -0,0 +1,581 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "mpa.h" + +/* + * Remove the #undef if you like debug print outs and assertions + * for this file. + */ +/*#undef DEBUG_ME */ +#include "mpa_debug.h" +#include "mpa_assert.h" + +/************************************************************* + * + * HELPERS + * + *************************************************************/ + +/*------------------------------------------------------------ + * + * These functions have ARM assembler implementations + * + */ +#if !defined(USE_ARM_ASM) + +/* -------------------------------------------------------------------- + * Function: __mpa_full_adder + * + * A word_t sized full adder. Incoming carry is in *carry. + * The sum will be put in *sum and the + * outgoing carry will be returned in *carry + */ +void __mpa_full_adder(mpa_word_t a, + mpa_word_t b, mpa_word_t *sum, mpa_word_t *carry) +{ +#if defined(MPA_SUPPORT_DWORD_T) + mpa_dword_t _s; + _s = (mpa_dword_t) (a) + (mpa_dword_t) (b) + (mpa_dword_t) (*carry); + *sum = (mpa_word_t) (_s); + *carry = ((mpa_word_t) (_s >> MPA_WORD_SIZE)); +#else + *sum = a + *carry; + *carry = (*sum < a); + *sum += b; + *carry += (*sum < b); +#endif +} + +/* -------------------------------------------------------------------- + * Function: __mpa_full_sub + * + * A word_t sized full subtraction function. Incoming carry is in *carry. + * The difference will be put in *diff and the outgoing carry will be returned + * in *carry. + */ +void __mpa_full_sub(mpa_word_t a, + mpa_word_t b, mpa_word_t *diff, mpa_word_t *carry) +{ +#if defined(MPA_SUPPORT_DWORD_T) + mpa_dword_t _d; + _d = (mpa_dword_t) (a) - (mpa_dword_t) (b) - (mpa_dword_t) (*carry); + *diff = (mpa_word_t) (_d); + *carry = 0 - (mpa_word_t) (_d >> WORD_SIZE); +#else + mpa_word_t _d; + *diff = a - *carry; + *carry = (*diff > a); + _d = *diff - b; + *carry += (_d > *diff); + *diff = _d; +#endif +} + +/*------------------------------------------------------------ + * + * __mpa_full_adder_ackum + * + * A word_t sized full adder with ackumulate. *d = *d + e + *carry + * Outgoing carry is in *carry + */ +void __mpa_full_adder_ackum(mpa_word_t *d, mpa_word_t e, mpa_word_t *carry) +{ +#if defined(MPA_SUPPORT_DWORD_T) + mpa_dword_t _s; + _s = (mpa_dword_t) (*d) + (mpa_dword_t) (e) + (mpa_dword_t) (*carry); + *d = (mpa_word_t) (_s); + *carry = ((mpa_word_t) (_s >> MPA_WORD_SIZE)); +#else + mpa_word_t _s; + _s = *d + *carry; + *carry = (_s < *d); + *d = _s + e; + *carry += (*d < _s); +#endif +} + +#endif /* of USR_ARM_ASM */ + +/* -------------------------------------------------------------------- + * Function: __mpa_abs_add + * + * Calculate |op1| + |op2|. + * op1 and op2 are pointers to word_t arrays holding the value. + * *Sum must be big enough to hold the result. + */ +void __mpa_abs_add(mpa_word_t *sum, + mpa_usize_t *sum_size, + const mpa_word_t *op1, + mpa_usize_t op1_size, + const mpa_word_t *op2, mpa_usize_t op2_size) +{ + const mpa_word_t *smaller; + const mpa_word_t *larger; + mpa_word_t *sum_begin; + mpa_usize_t smaller_wsize; /* size in words of the smallest */ + mpa_usize_t larger_wsize; /* size in words of the largest */ + mpa_word_t carry; + mpa_usize_t i; + + /* make sure we know which is the larger one */ + if (op1_size > op2_size) { + larger = op1; + smaller = op2; + larger_wsize = op1_size; + smaller_wsize = op2_size; + } else { /* op2 is the larger or same size */ + larger = op2; + smaller = op1; + larger_wsize = op2_size; + smaller_wsize = op1_size; + } + + sum_begin = sum; + carry = 0; + i = 0; + while (i < smaller_wsize) { + __mpa_full_adder(*(smaller++), *(larger++), sum++, &carry); + i++; + } + while (carry && (i < larger_wsize)) { + __mpa_full_adder(0, *(larger++), sum++, &carry); + i++; + } + + if (i < larger_wsize) { + /* carry did not propagate all the way, copy the rest */ + mpa_memcpy(sum, larger, WORDS_TO_BYTES(larger_wsize - i)); + sum += larger_wsize - i; + } + + if (carry != 0) + *(sum++) = carry; + *sum_size = (mpa_word_t) (sum - sum_begin); +} + +/* -------------------------------------------------------------------- + * Function: __mpa_abs_add_ackum + * + * Calculate dest = dest + src. Both dest and src must be positive + * dest must be big enough to hold the result. + */ +void __mpa_abs_add_ackum(mpanum dest, const mpanum src) +{ + const mpa_word_t *sdig; /* source digits */ + mpa_word_t *ddig; /* dest digits */ + mpa_word_t *dest_begin; + + mpa_word_t carry; + mpa_usize_t i; + + i = src->size - dest->size; + if (i <= 0) + i = 0; + mpa_memset(dest->d + dest->size, 0, (1 + i) * BYTES_PER_WORD); + + dest_begin = dest->d; + sdig = src->d; + ddig = dest->d; + i = 0; + carry = 0; + while (i < src->size) { + __mpa_full_adder_ackum(ddig++, *(sdig++), &carry); + /* + * _s = (mpa_dword_t)*(ddig) + (mpa_dword_t)*(sdig++) + + * (mpa_dword_t)carry; + * *(ddig++) = (mpa_word_t)(_s); + * carry = (mpa_word_t)(_s >> WORD_SIZE); + */ + i++; + } + while (carry) { + __mpa_full_adder_ackum(ddig++, 0, &carry); + /* + * _s = (mpa_dword_t)*(ddig) + (mpa_dword_t)carry; + * *(ddig++) = (mpa_word_t)(_s); + * carry = (mpa_word_t)(_s >> WORD_SIZE); + */ + } + i = (mpa_word_t) (ddig - dest_begin); + if (i > dest->size) + dest->size = i; +} + +/* -------------------------------------------------------------------- + * Function: __mpa_abs_sub + * + * Calculate |op1| - |op2|, where |op1| >= |op2| must hold. + * op1 and op2 are pointers to word_t arrays holding the value. + * *Diff must be big enough to hold the result. diff_size is + * updated with the number of significant words in *diff. + */ +void __mpa_abs_sub(mpa_word_t *diff, + mpa_usize_t *diff_size, + const mpa_word_t *op1, + mpa_usize_t op1_size, + const mpa_word_t *op2, mpa_usize_t op2_size) +{ + mpa_word_t carry; + mpa_usize_t i; + + carry = 0; + i = 0; + while (i < op2_size) { + __mpa_full_sub(*(op1++), *(op2++), diff++, &carry); + i++; + } + /* + * Here we have no more digits in op2, we only need to keep on + * subtracting 0 from op1, and deal with carry. + */ + while (carry && (i < op1_size)) { + __mpa_full_sub(*(op1++), 0, diff++, &carry); + i++; + } + + if (i < op1_size) { + /* + * Carry did not propagate all the way, now we only need to + * copy the rest. + */ + mpa_memcpy(diff, op1, WORDS_TO_BYTES(op1_size - i)); + diff += op1_size - i; + } + /* check size of diff */ + i = op1_size; + while ((i > 0) && (*(--diff) == 0)) + i--; + *diff_size = i; +} + +/************************************************************* + * + * LIB FUNCTIONS + * + *************************************************************/ + +/* -------------------------------------------------------------------- + * Function: mpa_add + * + * Adds op1 and op2 and puts the result in dest. Dest could be one of the + * operands. + */ +void mpa_add(mpanum dest, + const mpanum op1, const mpanum op2, mpa_scratch_mem pool) +{ + int sign_1; + int sign_2; + mpa_word_t size_1; + mpa_word_t size_2; + mpanum tmp_dest; + int mem_marker; + + MEMPOOL_MARKER(pool); + + size_1 = __mpanum_size(op1); + size_2 = __mpanum_size(op2); + + sign_1 = __mpanum_sign(op1); + sign_2 = __mpanum_sign(op2); + + /* Handle the case when dest is one of the operands */ + mem_marker = ((dest == op1) || (dest == op2)); + if (mem_marker) + mpa_alloc_static_temp_var(&tmp_dest, pool); + else + tmp_dest = dest; + + /* Check if we must do a subtraction or a addition. + * Remember, we're not allowed to modify op1 or op2. + */ + + if (sign_1 == sign_2) { /* same signs */ + /* tmp_dest = |op1| + |op2| or tmp_dest = -(|op1| + |op2|) */ + __mpa_abs_add(tmp_dest->d, &(tmp_dest->size), op1->d, size_1, + op2->d, size_2); + + if (sign_1 == MPA_NEG_SIGN) + __mpanum_neg(tmp_dest); + + } else { /* different signs */ + if (sign_1 == MPA_POS_SIGN) { /* op1 positive, op1 + (-op2) */ + if (__mpa_abs_greater_than(op1, op2)) { + /* |op1| > |op2| */ + + /* tmp_dest = |op1| - |op2| */ + __mpa_abs_sub(tmp_dest->d, &(tmp_dest->size), + op1->d, size_1, op2->d, size_2); + + } else { /* |op2| >= |op1| */ + /* tmp_dest = - ( |op2| - |op1|) */ + __mpa_abs_sub(tmp_dest->d, &(tmp_dest->size), + op2->d, size_2, op1->d, size_1); + __mpanum_neg(tmp_dest); + } + + } else { /* op2 positive, (-op1) + op2 */ + if (__mpa_abs_greater_than(op1, op2)) { + /* |op1| > |op2| */ + + /* tmp_dest = - (|op1| - |op2|) */ + __mpa_abs_sub(tmp_dest->d, &(tmp_dest->size), + op1->d, size_1, op2->d, size_2); + __mpanum_neg(tmp_dest); + } else { /* |op2| >= |op1| */ + /* tmp_dest = |op2| - |op1| */ + __mpa_abs_sub(tmp_dest->d, &(tmp_dest->size), + op2->d, size_2, op1->d, size_1); + } + } + } + + mpa_copy(dest, tmp_dest); + if (mem_marker) + mpa_free_static_temp_var(&tmp_dest, pool); + MEMPOOL_SANITY_CHECK(pool); +} + +/* -------------------------------------------------------------------- + * Function: mpa_sub + * + * Calculated op1 - op2 and stores the result in dest. Dest could be one of + * the operands. + */ +void mpa_sub(mpanum dest, + const mpanum op1, const mpanum op2, mpa_scratch_mem pool) +{ + int sign_1; + int sign_2; + mpa_word_t size_1; + mpa_word_t size_2; + mpanum tmp_dest; + int mem_marker; + + MEMPOOL_MARKER(pool); + + size_1 = __mpanum_size(op1); + size_2 = __mpanum_size(op2); + + sign_1 = __mpanum_sign(op1); + sign_2 = __mpanum_sign(op2); + + /* Handle the case when dest is one of the operands */ + mem_marker = ((dest == op1) || (dest == op2)); + if (mem_marker) + mpa_alloc_static_temp_var(&tmp_dest, pool); + else + tmp_dest = dest; + + /* + * Check if we must do a subtraction or a addition. Remember, + * we're not allowed to modify op1 or op2. + */ + if (sign_1 == sign_2) { /* same signs */ + if (sign_1 == MPA_POS_SIGN) { /* both positive, op1 - op2 */ + if (__mpa_abs_greater_than(op1, op2)) { + /* |op1| > |op2| */ + + __mpa_abs_sub(tmp_dest->d, &(tmp_dest->size), + op1->d, size_1, op2->d, size_2); + } else { /* |op1| <= |op2| */ + /* tmp_dest = - (|op2| - |op1|) */ + __mpa_abs_sub(tmp_dest->d, &(tmp_dest->size), + op2->d, size_2, op1->d, size_1); + __mpanum_neg(tmp_dest); + } + } else { + /* both negative, (-op1) - (-op2) = -(op1 - op2) */ + + if (__mpa_abs_greater_than(op1, op2)) { + /* |op1| > |op2| */ + + /* tmp_dest = -(|op1| - |op2|) */ + __mpa_abs_sub(tmp_dest->d, &(tmp_dest->size), + op1->d, size_1, op2->d, size_2); + __mpanum_neg(tmp_dest); + } else { /* |op1| <= |op2| */ + /* tmp_dest = |op2| - |op1| */ + __mpa_abs_sub(tmp_dest->d, &(tmp_dest->size), + op2->d, size_2, op1->d, size_1); + } + } + } else { /* different signs */ + if (sign_1 == MPA_POS_SIGN) { /* op1 positive, op1 - (-op2) */ + /* tmp_dest = |op1| + |op2| */ + __mpa_abs_add(tmp_dest->d, &(tmp_dest->size), op1->d, + size_1, op2->d, size_2); + } else { /* op2 positive, (-op1) - op2 = - (op1 + op2) */ + /* tmp_dest = -(|op1| + |op2|) */ + __mpa_abs_add(tmp_dest->d, &(tmp_dest->size), op1->d, + size_1, op2->d, size_2); + __mpanum_neg(tmp_dest); + } + } + + mpa_copy(dest, tmp_dest); + if (mem_marker) + mpa_free_static_temp_var(&tmp_dest, pool); + MEMPOOL_SANITY_CHECK(pool); +} + +/* -------------------------------------------------------------------- + * Function: mpa_neg + * + * Assigns dest the value of src, but with a change of sign. Dest and src + * could be the same variable. + */ +void mpa_neg(mpanum dest, const mpanum src) +{ + mpa_copy(dest, src); + __mpanum_neg(dest); +} + +/* -------------------------------------------------------------------- + * Function: mpa_add_word + * + * Add a word_t (op2) to op1 and put result in dest + */ +void mpa_add_word(mpanum dest, + const mpanum op1, mpa_word_t op2, mpa_scratch_mem pool) +{ + int sign_1; + mpanum tmp_dest; + mpa_word_t size_1; + int mem_marker; + + MEMPOOL_MARKER(pool); + + if (op2 == 0) { + mpa_copy(dest, op1); + return; + } + + if (__mpanum_is_zero(op1)) { + dest->size = 1; + dest->d[0] = op2; + return; + } + + sign_1 = __mpanum_sign(op1); + size_1 = __mpanum_size(op1); + + /* handle the case when dest is the operand */ + mem_marker = (dest == op1); + if (mem_marker) + mpa_alloc_static_temp_var(&tmp_dest, pool); + else + tmp_dest = dest; + + /* find out if we should do an add or a sub, op2 is always positive */ + if (sign_1 == MPA_POS_SIGN) { /* add */ + /* tmp_dest = |op1| + op2 */ + __mpa_abs_add(tmp_dest->d, &(tmp_dest->size), op1->d, size_1, + &op2, 1); + } else { /* sub, op1 is negative: (-op1) + op2 */ + if (__mpanum_size(op1) > 1 || __mpanum_lsw(op1) > op2) { + /* |op1| > |op2| */ + + /* tmp_dest = - (|op1| - op2) */ + __mpa_abs_sub(tmp_dest->d, &(tmp_dest->size), op1->d, + size_1, &op2, 1); + __mpanum_neg(tmp_dest); + } else { /* op2 >= |op1| */ + /* tmp_dest = op2 - |op1| */ + tmp_dest->d[0] = op2 - op1->d[0]; + tmp_dest->size = (tmp_dest->d[0] == 0) ? 0 : 1; + } + } + + mpa_copy(dest, tmp_dest); + if (mem_marker) + mpa_free_static_temp_var(&tmp_dest, pool); + MEMPOOL_SANITY_CHECK(pool); +} + +/* -------------------------------------------------------------------- + * Function: mpa_sub_word + * + * Calculate op1 - op2, op2 is a word_t and always positive. + */ +void mpa_sub_word(mpanum dest, + const mpanum op1, mpa_word_t op2, mpa_scratch_mem pool) +{ + int sign_1; + mpanum tmp_dest; + mpa_word_t size_1; + char mem_marker; + + MEMPOOL_MARKER(pool); + + if (op2 == 0) { + mpa_copy(dest, op1); + return; + } + + if (__mpanum_is_zero(op1)) { + dest->size = -1; + dest->d[0] = op2; + return; + } + + sign_1 = __mpanum_sign(op1); + size_1 = __mpanum_size(op1); + + /* handle the case when dest is the operand */ + mem_marker = (dest == op1); + if (mem_marker) + mpa_alloc_static_temp_var(&tmp_dest, pool); + else + tmp_dest = dest; + + /* + * Find out if we should do an add or a sub, op2 is always positive + * + * dest = op1 - op2 if op1 > op2 >= 0 + * dest = -(op2 - op1) if op2 >= op1 >= 0 + * dest = -(|op1| + op2) if op1 < 0 + * + */ + if (sign_1 == MPA_POS_SIGN) { + if (__mpanum_size(op1) > 1 || __mpanum_lsw(op1) > op2) { + __mpa_abs_sub(tmp_dest->d, &(tmp_dest->size), op1->d, + size_1, &op2, 1); + } else { + tmp_dest->d[0] = op2 - op1->d[0]; + tmp_dest->size = (tmp_dest->d[0] == 0) ? 0 : -1; + } + } else { + __mpa_abs_add(tmp_dest->d, &(tmp_dest->size), op1->d, size_1, + &op2, 1); + __mpanum_neg(tmp_dest); + } + + mpa_copy(dest, tmp_dest); + if (mem_marker) + mpa_free_static_temp_var(&tmp_dest, pool); + MEMPOOL_SANITY_CHECK(pool); +} diff --git a/lib/libmpa/mpa_arm_asm.s b/lib/libmpa/mpa_arm_asm.s new file mode 100644 index 00000000000..590de2b0c9d --- /dev/null +++ b/lib/libmpa/mpa_arm_asm.s @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + .syntax unified + .thumb + .section .text + .align 2 + + .global __mpa_full_adder + .global __mpa_full_sub + .global __mpa_full_adder_ackum + .global __mpa_div_dword + .global __mpa_mul_add_word + .global __mpa_mul_add_word_cum + .global __mpa_montgomery_mul_add + .global __mpa_montgomery_sub_ack + +@ -------------------------------------------------------------------- +@ Function: __mpa_full_adder +@ +@ A word_t sized full adder. Incoming carry is in *carry. +@ The sum will be put in *sum and the +@ outgoing carry will be returned in *carry +@ +@ void __mpa_full_adder( mpa_word_t a, +@ mpa_word_t b, +@ mpa_word_t* sum, +@ mpa_word_t* carry) +@ + .thumb_func + .type __mpa_full_adder, %function +__mpa_full_adder: + push {r9} + ldr r9, [r3] @ r9 holds incoming carry + adds r1, r1, r0 @ r1 holds b + a + mov r12, #0 @ + adc r0, r12, #0 @ r0 holds carry of a + b + adds r1, r1, r9 @ r1 holds a + b + incoming carry + str r1, [r2] @ *sum <- r1 + adc r0, r0, #0 @ r0 holds acc carry + str r0, [r3] @ *carry <- r0 + pop {r9} + bx lr + +@ -------------------------------------------------------------------- +@ Function: __mpa_full_sub +@ +@ A word_t sized full subtraction function. Incoming carry is in *carry +@ The difference will be put in *diff and the outgoing carry will be returned +@ in *carry +@ +@ void __mpa_full_sub(mpa_word_t a, +@ mpa_word_t b, +@ mpa_word_t* diff, +@ mpa_word_t* carry); +@ + .thumb_func + .type __mpa_full_sub, %function +__mpa_full_sub: + push {r9} + ldr r9, [r3] @ r9 holds incomming carry + subs r1, r0, r1 @ r1 holds a - b + mov r12, #0 + sbc r0, r12, #0 @ r0 holds carry + subs r1, r1, r9 @ r1 holds a - b - carry + str r1, [r2] @ *diff <- r1 + sbc r0, r0, #0 @ r0 <- r0 - carry + rsbs r0, r0, #0 @ r0 <- 0 - r0 outgoing carry + str r0, [r3] @ *carry <- r0 + pop {r9} + bx lr + +@ -------------------------------------------------------------------- +@ Function: __mpa_full_adder_ackum +@ +@ A word_t sized full adder with ackumulate. *d = *d + e + *carry +@ Outgoing carry is in *carry +@ +@ void __mpa_full_adder_ackum( mpa_word_t* d, +@ mpa_word_t e, +@ mpa_word_t* carry) +@ + .thumb_func + .type __mpa_full_adder_ackum, %function +__mpa_full_adder_ackum: + push {r9} + ldr r12, [r0] @ r12 <- *d + mov r9, #0 @ + ldr r3, [r2] @ r3 holds incoming carry + adds r1, r1, r12 @ r1 <- e + *d + adc r9, r9, #0 @ r9 <- carry + adds r1, r1, r3 @ r1 <- r1 + *carry + str r1, [r0] @ *d <- sum + adc r0, r9, #0 @ r0 <- outgoing carry + str r0, [r2] @ *carry <- carry + pop {r9} + bx lr + + +@ -------------------------------------------------------------------- +@ Function: __mpa_div_dword +@ +@ Wrapper for the soft div. Calculates quotient and remainder of +@ ((x1 << WORD_SIZE) + x0 ) / y +@ +@ mpa_word_t __mpa_div_dword(mpa_word_t x0, +@ mpa_word_t x1, +@ mpa_word_t y, +@ mpa_word_t* rem) +@ +@ returns the quotient in r0 and the remainder in *rem +@ +@ At entrace +@ r0 low32 of num +@ r1 high32 of num +@ r2 y (becomes high32 of den) +@ r3 addr of rem + .thumb_func + .type __mpa_div_dword, %function +__mpa_div_dword: + push {r4, r5, r6, r7, r8, r9, lr}@ + + mov r12, #0 @ r12 holds low32 of den + @ r2 holds high32 of den + mov lr, #1 @ lr holds high32 of qbit + movs r4, #0 @ r4 holds low32 of qbit + cmp r2, #-1 @ if den >= 0 + bgt normalize @ branch to normalize + mov r9, #0 @ r9 holds low of quot + mov r8, #0 @ r8 holds high of quot + +soft_div_main: + cmp r12, r0 @ cmp low(den) low(num) + mov r6, #0 @ + it hi @ + movhi r6, #1 @ r6 is 1 if low(den) > low(num) + cmp r2, r1 @ cmp high(den) high(num) + mov r5, #0 @ + it hi @ + movhi r5, #1 @ r5 if 1 if high(den) > high(num) + it eq @ + moveq r5, r6 @ if high is equal let low decide + cbnz r5, shift_right @ if r5 == 1 branch + + adds r9, r9, r4 @ quot += qbit + adc r8, r8, lr @ + subs r0, r0, r12 @ num -= den + sbcs r1, r2 @ + +shift_right: +@ +@ These right shifts should be done as +@ +@ lsrs r2, r2, #1 @ right shift den >>= 1 +@ rrx r12, r12 +@ lsrs lr, lr, #1 @ right shift qbit >>= 1 +@ rrx r4, r4 +@ +@ but due to a compiler error in the STE toolchain (2012-05-03) +@ we must implement this as: + + and r7, r2, #1 + mov r2, r2, lsr #1 + mov r7, r7, lsl #31 + mov r12, r12, lsr #1 + orr r12, r12, r7 + + and r7, lr, #1 + mov lr, lr, lsr #1 + mov r7, r7, lsl #31 + mov r4, r4, lsr #1 + orr r4, r4, r7 + +@ +@ end of compiler bug fix +@ + orrs r5, r4, lr @ while qbit != 0 + bne soft_div_main @ do mainloop + +store_and_exit: + cmp r3, #0 @ if (r != NULL) + it ne @ + strne r0, [r3] @ store remainder into *r + mov r0, r9 @ + pop {r4, r5, r6, r7, r8, r9, pc}@ clean up and exit + +normalize: + adds r4, r4, r4 @ qbit <<= 1 + adc lr, lr, lr @ + adds r12, r12, r12 @ den <<= 1 + adcs r2, r2 @ + cmp r2, #-1 @ while den >= 0 + bgt normalize @ do normalize + + mov r9, #0 @ + orrs r6, r4, lr @ if qbit == 0 + beq store_and_exit @ done, branch to store r and exit + + mov r8, r9 @ set quot = 0 (r9 = 0 r8 = 0) + b soft_div_main @ and branch to main loop + + +@ -------------------------------------------------------------------- +@ Function: __mpa_mul_add_word +@ +@ Multiplies a and b and adds the incoming carry tp produce the product. +@ Outgoing carry is stored in *carry +@ +@ void __mpa_mul_add_word(mpa_word_t a, +@ mpa_word_t b, +@ mpa_word_t* p, +@ mpa_word_t* carry) +@ +@ + .thumb_func + .type __mpa_mul_add_word, %function +__mpa_mul_add_word: + push {r9} + umull r1, r9, r1, r0 @ r1, r9 <- a * b + ldr r0, [r3] @ r0 <- incoming carry + adds r1, r1, r0 @ add incoming carry to product + str r1, [r2] @ store low32 of product + adc r0, r9, #0 @ add carry to high32 + str r0, [r3] @ store outgoing carry + pop {r9} + bx lr + +@ -------------------------------------------------------------------- +@ Function: __mpa_mul_add_word_cum +@ +@ Multiplies a and b and adds the incoming carry and the cumulative +@ product. +@ Outgoing carry is stored in *carry +@ +@ void __mpa_mul_add_word_cum(mpa_word_t a, +@ mpa_word_t b, +@ mpa_word_t* p, +@ mpa_word_t* carry) +@ +@ + .thumb_func + .type __mpa_mul_add_word_cum, %function +__mpa_mul_add_word_cum: + push {r9} + umull r12, r9, r1, r0 @ r9, r12 <- a * b + ldr r0, [r2] @ r0 holds incoming product + ldr r1, [r3] @ r1 holds incoming carry + adds r0, r0, r12 @ r0 holds incoming product + new low32 + adc r9, r9, #0 @ add carry to high32 + adds r0, r0, r1 @ add incoming carry + str r0, [r2] @ store outgoing product + adc r0, r9, #0 @ store outgoing carry in r0 + str r0, [r3] @ and write to [r3] + pop {r9} + bx lr + + +@ -------------------------------------------------------------------- +@ Function: __mpa_montgomery_mul_add +@ +@ Calculates dest = dest + src * w +@ Dest must be big enough to hold the result +@ +@ void __mpa_montgomery_mul_add(mpanum dest, +@ mpanum src, +@ mpa_word_t w) +@ + .thumb_func + .type __mpa_montgomery_mul_add, %function +__mpa_montgomery_mul_add: + push {r4, r5, r6, r7, lr} + add r7, sp, #12 + push {r8, r9, r10, r11} + cbz r2, mm_mul_add_exit @ if w == 0 return + ldr r3, [r1, #4] @ r3 holds src->size + add r9, r0, #8 @ r9 holds &dest->d (dest_begin) + cmp r3, #1 @ + mov r3, r9 @ r3 holds &dest->d (ddig) + blt mm_mul_add_check_size @ if src->size == NULL jump + add r12, r1, #8 @ r12 holds &src->d + mov lr, #0 @ + movs r3, #0 @ + movs r4, #0 @ r4 holds carry + movs r5, #0 @ r5 holds inx + +mm_main_loop: + ldr r6, [r12, r5, lsl #2] @ r6 holds src->d[idx] + adds r3, #4 + ldr r11, [r9, r5, lsl #2] @ r11 holds dest->d[idx] + umull r10, r8, r6, r2 @ r8, r10 holds src->d[idx] * w + mla r8, r6, lr, r8 @ r8 <- r6*0 + r8 ?? + adds r6, r11, r4 @ r6 <- dest->d[idx] + carry + adc r4, lr, #0 @ r4 holds C + adds r6, r6, r10 @ r6 holds low32 of result + str r6, [r9, r5, lsl #2] @ store into dest->d[idx] + add r5, r5, #1 @ idx++ + ldr r6, [r1, #4] @ r6 holds src->size + adc r4, r4, r8 @ r4 holds high32 of result + cmp r5, r6 @ while (idx < src->size) + blt mm_main_loop @ do jump + + adds r1, r0, r3 @ + cmp r4, #0 @ check carry + add r3, r1, #8 @ r3 holds &dest->d[idx] + beq mm_mul_add_check_size @ jump if no carry + movs r1, #0 + +mm_carry_loop: + ldr r2, [r3] @ r2 holds dest->d[idx] + adds r2, r2, r4 @ r2 <- r2 + carry + str r2, [r3], #4 @ store at dest->d[idx++] + adcs r4, r1, #0 @ r4 holds new C + bne mm_carry_loop @ if r4 != 0 jump + +mm_mul_add_check_size: + sub r1, r3, r9 @ r1 holds ddig - dest_begin + ldr r2, [r0, #4] @ r2 holds dest->size + asrs r1, r1, #2 @ mult by 2 to go from byte addr to word + cmp r1, r2 @ + it gt @ + strgt r1, [r0, #4] @ store new size if idx > dest->size + +mm_mul_add_exit: + pop {r8, r9, r10, r11} + pop {r4, r5, r6, r7, pc} + + +@ -------------------------------------------------------------------- +@ Function: __mpa_montgomery_sub_ack +@ Calculates dest = dest - src +@ Assumption: dest >= src and both non-negative +@ and dest > src. +@ +@ +@ void __mpa_montgomery_sub_ack(mpanum dest, +@ mpanum src) +@ + .thumb_func + .type __mpa_montgomery_sub_ack, %function +__mpa_montgomery_sub_ack: + push {r4, r5, r7, r9, lr} + ldr r2, [r1, #4] + add r9, r0, #8 + mov lr, #0 + add r7, sp, #8 + cmp r2, #0 + bgt LBB1_10 + movs r2, #0 + b LBB1_6 +LBB1_2: + cbz r4, LBB1_6 + movs r1, #0 + LBB1_4: + add r5, r0, r2, lsl #2 + adds r3, #4 + adds r2, #1 + ldr r4, [r5, #8] + subs r4, r4, r12 + str r4, [r5, #8] + sbcs r5, r1, #0 + rsb r12, r5, #0 + bne LBB1_4 + add r9, r0, r3 +LBB1_6: + ldr r3, [r0, #4] + cmp r2, r3 + blt LBB1_12 + sub r1, r9, #4 + subs r2, r3, #1 +LBB1_8: + adds r3, r2, #1 + cmp r3, #1 + blt LBB1_12 + ldr r3, [r1] + cmp r3, #0 + it ne + popne {r4, r5, r7, r9, pc} + str r2, [r0, #4] + subs r2, #1 + subs r1, #4 + b LBB1_8 +LBB1_10: + movs r3, #8 + movs r2, #0 + mov r12, #0 +LBB1_11: + add r5, r1, r2, lsl #2 + ldr r4, [r9] + adds r3, #4 + adds r2, #1 + ldr r5, [r5, #8] + subs r5, r4, r5 + sbc r4, lr, #0 + subs r5, r5, r12 + str r5, [r9], #4 + sbc r4, r4, #0 + ldr r5, [r1, #4] + rsb r12, r4, #0 + cmp r2, r5 + blt LBB1_11 + b LBB1_2 +LBB1_12: + pop {r4, r5, r7, r9, pc} + + diff --git a/lib/libmpa/mpa_cmp.c b/lib/libmpa/mpa_cmp.c new file mode 100644 index 00000000000..a2e0ab46232 --- /dev/null +++ b/lib/libmpa/mpa_cmp.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "mpa.h" + +/* + * Remove the #undef if you like debug print outs and assertions + * for this file. + */ +/*#undef DEBUG_ME */ +#include "mpa_debug.h" +#include "mpa_assert.h" + +/************************************************************* + * + * HELPERS + * + *************************************************************/ + +/* -------------------------------------------------------------------- + * Function: __mpa_abs_cmp + * + * Returns 0 if |op1| == |op2| + * >0 if |op1| > |op2| + * <0 if |op1| < |op2| + */ +int __mpa_abs_cmp(const mpanum op1, const mpanum op2) +{ + int wpos; + char same; + + /* if they're really the same, return 0 */ + if (op1 == op2) + return 0; + + /* check the sizes */ + if (__mpanum_size(op1) != __mpanum_size(op2)) + return __mpanum_size(op1) - __mpanum_size(op2); + + if (__mpanum_is_zero(op1) && __mpanum_is_zero(op2)) + return 0; + + /* Ok, so we have the same size and they're not zero. Check words */ + wpos = __mpanum_size(op1) - 1; + same = 1; + while (same && (wpos >= 0)) { + same = (op1->d[wpos] == op2->d[wpos]); + wpos--; + } + if (same) + return 0; + wpos++; + return (op1->d[wpos] > op2->d[wpos] ? 1 : -1); +} + +/* -------------------------------------------------------------------- + * Function: __mpa_abs_greater_than + * + * Returns 1 if |op1| > |op2| and otherwise returns 0. + */ +int __mpa_abs_greater_than(const mpanum op1, const mpanum op2) +{ + return (__mpa_abs_cmp(op1, op2) > 0 ? 1 : 0); +} + +/* -------------------------------------------------------------------- + * Function: __mpa_abs_less_than + * + * Returns 1 if |op1| < |op2| and otherwise returns 0. + */ +int __mpa_abs_less_than(const mpanum op1, const mpanum op2) +{ + return (__mpa_abs_cmp(op1, op2) < 0 ? 1 : 0); +} + +/************************************************************* + * + * LIB FUNCTIONS + * + *************************************************************/ + +/* -------------------------------------------------------------------- + * Function: mpa_cmp + * + * Returns 0 if op1 == op2 + * >0 if op1 > op2 + * <0 if op1 < op2 + */ +int32_t mpa_cmp(const mpanum op1, const mpanum op2) +{ + int sign_1; + int abscmp; + + /* if they have different signs, it's straight forward */ + sign_1 = __mpanum_sign(op1); + if (sign_1 != __mpanum_sign(op2)) + return sign_1; + + /* handle the special case where op1->size = 0 */ + if (__mpanum_size(op1) == 0) + return __mpanum_size(op2) == 0 ? 0 : -__mpanum_sign(op2); + + /* so they have the same sign. compare the abs values and decide + * based on sign_1. + */ + + abscmp = __mpa_abs_cmp(op1, op2); + if (sign_1 != MPA_POS_SIGN) + return -abscmp; + return abscmp; +} + +/* -------------------------------------------------------------------- + * Function: mpa_cmp_short + * + * Compares op1 to the word_t op2 and returns: + * >0 if op1 > op2, + * 0 if op1 == op2 + * <0 if op1 < op2 + */ +int32_t mpa_cmp_short(const mpanum op1, int32_t op2) +{ +#if (MPA_WORD_SIZE == 32) + + int sign_1; + int sign_2; + mpa_word_t op2abs; + + sign_1 = __mpanum_sign(op1); + sign_2 = (op2 < 0) ? MPA_NEG_SIGN : MPA_POS_SIGN; + + /* handle the special case where op1->size = 0 */ + if (op1->size == 0) + return op2 == 0 ? 0 : -sign_2; + + /* check if op1 is larger than an int32_t */ + if (__mpanum_size(op1) > 1) + return sign_1; + + /* check if they have different signs */ + if (sign_1 != sign_2) + return sign_1; + + /* here they have the same sign and we can compare absolute values */ + + op2abs = ((op2 < 0) ? (mpa_word_t) -op2 : (mpa_word_t) op2); + + if (__mpanum_lsw(op1) == op2abs) + return 0; + + return (__mpanum_lsw(op1) > op2abs) ? sign_1 : -sign_1; + +#else +#error "Write code for digit size != 32" +#endif +} diff --git a/lib/libmpa/mpa_conv.c b/lib/libmpa/mpa_conv.c new file mode 100644 index 00000000000..3e0e4a5b781 --- /dev/null +++ b/lib/libmpa/mpa_conv.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "mpa.h" + +/* + * Remove the #undef if you like debug print outs and assertions + * for this file. + */ +/*#undef DEBUG_ME */ +#include "mpa_debug.h" +#include "mpa_assert.h" + +/*------------------------------------------------------------ + * + * mpa_set_S32 + * + */ +void mpa_set_S32(mpanum dest, int32_t short_val) +{ +#if (MPA_WORD_SIZE == 32) + if (short_val != 0) + dest->size = (short_val < 0) ? -1 : 1; + else + dest->size = 0; + dest->d[0] = (short_val < 0) ? -short_val : short_val; +#else +#error "Write code for digit size != 32" +#endif +} + +/*------------------------------------------------------------ + * + * mpa_get_S32 + * + * Returns zero if the src fits within an int32_t + * otherwise it returns non-zero and the dest value is undefined. + */ +int32_t mpa_get_S32(int32_t *dest, mpanum src) +{ +#if (MPA_WORD_SIZE == 32) + if (__mpanum_size(src) > 1) + return -1; + if (__mpanum_lsw(src) > INT32_MIN && __mpanum_sign(src) == MPA_NEG_SIGN) + return -1; + if (__mpanum_lsw(src) > INT32_MAX && __mpanum_sign(src) == MPA_POS_SIGN) + return -1; + + *dest = __mpanum_get_word(0, src) * __mpanum_sign(src); + return 0; + +#else +#error "Write code for digit size != 32" +#endif +} + +/*------------------------------------------------------------ + * + * mpa_set_word + * + */ +void mpa_set_word(mpanum dest, mpa_word_t src) +{ + dest->d[0] = src; + dest->size = (src == 0) ? 0 : 1; +} + +/*------------------------------------------------------------ + * + * mpa_get_word + * + * Returns the absolute value of the least significant word of src + */ +mpa_word_t mpa_get_word(mpanum src) +{ + return __mpanum_get_word(0, src); +} diff --git a/lib/libmpa/mpa_debug.c b/lib/libmpa/mpa_debug.c new file mode 100644 index 00000000000..ffe033165b5 --- /dev/null +++ b/lib/libmpa/mpa_debug.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "mpa.h" +#include "mpa_debug.h" + +#if defined(DEBUG) + +FILE *logfd = stdout; + +#if defined(__x86_64) +#include +/*------------------------------------------------------------ + * + * __mpa_dbg_print_stack + * + */ +void __mpa_dbg_print_stack() +{ + fprintf(logfd, "Cannot print stack with __x86_64\n"); +} +#else +void __mpa_dbg_print_stack() +{ + fprintf(logfd, "Cannot print stack. (execinfo.h not included)\n"); +} +#endif + +/* -------------------------------------------------------------------- + * Function: __mpa_dbg_print_header + * Used to print the filename and line number before DPRINTs + * + */ +void __mpa_dbg_print_header(const char *f_str, const int l_num) +{ + fprintf(logfd, "DEBUG: %s:%d:", f_str, l_num); + fflush(logfd); +} + +/* -------------------------------------------------------------------- + * Function: __mpa_dbg_print + * + * + */ +void __mpa_dbg_print(const char *format, ...) +{ + va_list varg; + va_start(varg, format); + vfprintf(logfd, format, varg); + va_end(varg); + fflush(logfd); +} + +/* -------------------------------------------------------------------- + * Function: __mpa_dbg_dump_mpanum + * Prints the internal values of a TEE_BigInt + * + */ +void __mpa_dbg_dump_mpanum(mpanum a) +{ + int i; + + fprintf(logfd, " ---- Dump :\n"); + fprintf(logfd, " mpanum->size = %d\n", a->size); + fprintf(logfd, " mpanum->alloc = %u\n", a->alloc); + fprintf(logfd, " mpanum->d (MSW to LSW) :\n"); + for (i = __mpanum_alloced(a) - 1; i >= __mpanum_size(a); i--) + fprintf(logfd, "%.8X ", a->d[i]); + fprintf(logfd, "\n"); + for (i = __mpanum_size(a) - 1; i >= 0; i--) + fprintf(logfd, "[%d] : %.8X\n", i, a->d[i]); + fflush(logfd); +} + +/* -------------------------------------------------------------------- + * __mpa_dbg_print_mpanum_hex. Prints the value of a in hex. + * + */ +void __mpa_dbg_print_mpanum_hexstr(const mpanum val) +{ + static char _str_[MPA_STR_MAX_SIZE]; + mpa_get_str(_str_, MPA_STRING_MODE_HEX_UC, 8, val); + fprintf(logfd, "%s", _str_); + fflush(logfd); +} + +#endif diff --git a/lib/libmpa/mpa_div.c b/lib/libmpa/mpa_div.c new file mode 100644 index 00000000000..08de4220220 --- /dev/null +++ b/lib/libmpa/mpa_div.c @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "mpa.h" + +/* + * Remove the #undef if you like debug print outs and assertions + * for this file. + */ +/*#undef DEBUG_ME */ +#include "mpa_debug.h" +#include "mpa_assert.h" + +/************************************************************* + * + * HELPER FUNCTIONS + * + *************************************************************/ + +/*------------------------------------------------------------ + * + * These functions have ARM assembler implementations + * + */ +#if !defined(USE_ARM_ASM) + +static mpa_dword_t __mpa_soft_div(mpa_dword_t num, mpa_word_t den_in, + mpa_word_t *rem) +{ + mpa_dword_t quot = 0, qbit = 1; + mpa_dword_t den = den_in; + + while ((int64_t) den >= 0) { + den <<= 1; + qbit <<= 1; + } + + while (qbit) { + if (den <= num) { + num -= den; + quot += qbit; + } + den >>= 1; + qbit >>= 1; + } + + if (rem) + *rem = (mpa_word_t) num; + + return quot; +} + +/* -------------------------------------------------------------------- + * Function: __mpa_div_dword + * + * Calculates quotient and remainder of (n1*base + n0) / d. + * It is assumed that the quotient is small enough to fit a single word. + */ +mpa_word_t __mpa_div_dword(mpa_word_t n0, + mpa_word_t n1, mpa_word_t d, mpa_word_t *r) +{ +#if defined(MPA_SUPPORT_DWORD_T) + mpa_dword_t n; + /* mpa_dword_t tmp_q; */ + + n = ((mpa_dword_t) n1 << WORD_SIZE) + n0; + return __mpa_soft_div(n, d, r); + /* tmp_q = n / d; */ + /* *r = (mpa_word_t)(n % d); */ + /* return tmp_q; */ +#else +#error write non-dword code for __mpa_div_dword +#endif +} + +#endif /* USE_ARM_ASM */ + +/* -------------------------------------------------------------------- + * Function: __mpa_div_q_r_internal + * + * Finds the quotient and remainder when |op1| is divided by |op2|. + * q, r, op1 and op2 must all be distinct and not null. + * E.i. we get q and r such that |op1| = q*|op2| + r, 0<= r < |op2|. + * Assumptions: |op1| >= |op2| and |op2| >= 2^(WORD_SIZE) + * + */ +static void __mpa_div_q_r_internal(mpanum q, + mpanum r, + const mpanum op1, + const mpanum op2, mpa_scratch_mem pool) +{ + mpa_word_t normshift; + int base_diff; + int i; + int cmp_same; + mpa_usize_t n; /* size of op1 */ + mpa_usize_t t; /* size of op2 */ + mpa_word_t w1; + mpa_word_t w2; + mpa_word_t w3; + mpa_word_t w4; + mpa_word_t w5; + mpanum p; + mpanum y; + mpanum x; + + /* + * get temp storage + */ + mpa_alloc_static_temp_var(&p, pool); + mpa_alloc_static_temp_var(&y, pool); + mpa_copy(y, op2); + + /* + * May need a large value for r since op1 may be an "oversized" + * value that is reduced. x is used for that internally and it's + * initial value is op1. + */ + mpa_alloc_static_temp_var(&x, pool); + mpa_copy(x, op1); + __mpanum_set_sign(x, MPA_POS_SIGN); + __mpanum_set_sign(y, MPA_POS_SIGN); + + /* + * Normalization + */ + normshift = 0; + w1 = __mpanum_msw(y); + while (w1 < (1 << (WORD_SIZE - 1))) { + normshift++; + w1 <<= 1; + } + if (normshift) { + mpa_shift_left(x, x, normshift); + mpa_shift_left(y, y, normshift); + } + + n = x->size; + t = y->size; + base_diff = (int)n - t; + + mpa_wipe(q); + + /* + * check if op1 >= op2*base^(base_diff) + */ + /* mpa_shift_left(y, y, base_diff * WORD_SIZE); */ + __mpa_shift_words_left(y, base_diff); + + i = __mpanum_size(y); + cmp_same = 1; + while (cmp_same != 0 && i > 0) { + i--; + cmp_same = (__mpanum_get_word(i, x) == __mpanum_get_word(i, y)); + } + if (!cmp_same && (__mpanum_get_word(i, x) > __mpanum_get_word(i, y))) { + q->d[base_diff] = 1; + mpa_sub(x, x, y, pool); + } + + /* start main division loop */ + i = x->size - 1; + while (i >= (int)t) { + if (__mpanum_get_word(i, x) == + __mpanum_get_word(t + base_diff - 1, y)) { + q->d[i - t] = WORD_ALL_BITS_ONE; + } else { + q->d[i - t] = + __mpa_div_dword(__mpanum_get_word(i - 1, x), + __mpanum_get_word(i, x), + __mpanum_get_word(t + base_diff + - 1, y), + NULL); + } + while (1) { + /* set incoming carry to zero for all three ops */ + w1 = 0; + w3 = 0; + w5 = 0; + __mpa_mul_add_word(q->d[i - t], + __mpanum_get_word(t + base_diff - 1, + y), &w2, &w1); + + if (w1 > __mpanum_get_word(i, x)) + goto loop_dec; + + __mpa_mul_add_word(q->d[i - t], + __mpanum_get_word(t + base_diff - 2, + y), &w4, &w3); + + __mpa_full_adder(w2, w3, &w3, &w5); + w2 = 0; /* used as carry */ + __mpa_full_adder(w1, w5, &w5, &w2); + if (w2 || w5 > __mpanum_get_word(i, x)) + goto loop_dec; + if (w5 < __mpanum_get_word(i, x)) + break; + if (w3 > __mpanum_get_word(i - 1, x)) + goto loop_dec; + if (w3 < __mpanum_get_word(i - 1, x)) + break; + if (w4 > __mpanum_get_word(i - 2, x)) + goto loop_dec; + break; +loop_dec: + q->d[i - t]--; + } + + /* mpa_shift_right(y, y, WORD_SIZE); */ + __mpa_shift_words_right(y, 1); + base_diff--; + mpa_mul_word(p, y, q->d[i - t], pool); + mpa_sub(x, x, p, pool); + if (__mpanum_sign(x) == MPA_NEG_SIGN) { + mpa_add(x, x, y, pool); + q->d[i - t]--; + } + i--; + } + /* + * Find size of q + */ + i = n - t; + while (i >= 0 && q->d[i] == 0) + i--; + q->size = i + 1; + /* + * Divide r by the normalization value and copy to output + */ + mpa_shift_right(x, x, normshift); + mpa_copy(r, x); + + /* + * release p, y, and x + */ + mpa_free_static_temp_var(&p, pool); + mpa_free_static_temp_var(&y, pool); + mpa_free_static_temp_var(&x, pool); +} + +/* -------------------------------------------------------------------- + * Function: __mpa_div_q_r_internal_word + * + * Finds the quotient and remainder when |op1| is divided by |op2|, where + * op2 is a word. + * q, r and op1 must all be distinct and not null. + * E.i. we get q and r such that |op1| = q*|op2| + r, 0<= r < |op2|. + * Assumptions: |op1| >= |op2|. + + */ +void __mpa_div_q_r_internal_word(mpanum q, + mpanum r, + const mpanum op1, const mpa_word_t op2) +{ + int pos1; + mpa_word_t q_word; + mpa_word_t r_word; + mpa_word_t n1; + mpa_word_t n0; + int i; + + if (__mpanum_size(op1) == 1) { + mpa_set_word(q, op1->d[0] / op2); + mpa_set_word(r, op1->d[0] % op2); + return; + } + mpa_copy(r, op1); + mpa_set_word(q, 0); + + pos1 = (int)__mpanum_size(r) - 1; + n1 = 0; + n0 = r->d[pos1]; + while (pos1 >= 0) { + q_word = __mpa_div_dword(n0, n1, op2, &r_word); + q->d[pos1] = q_word; + r->d[pos1] = r_word; + n1 = r->d[pos1]; + n0 = r->d[--pos1]; + } + /* set sizes of r and q */ + r->size = (r->d[0] == 0 ? 0 : 1); + i = __mpanum_size(op1) - 1; + while (i >= 0 && q->d[i] == 0) + i--; + q->size = i + 1; +} + +/* -------------------------------------------------------------------- + * Function: __mpa_div_q_r + * + * Calculates the quotient and remainder when op1 is divided by op2. + * q, r, op1 and op2 must all be distinct and not null, except that op1 + * may be equal to op2. + * There must be enough space allocated in q and r to handle the results. + * If op2 is zero a division with zero will be executed and the above layers + * can handle that as it pleases. + * The sign of q and r are shown in the table: + * __________________________________ + * | Sign(q/r) | op1 >= 0 | op1 < 0 | + * |--------------------------------| + * | op2 > 0 | +/+ | -/- | + * |--------------------------------| + * | op2 < 0 | -/+ | +/- | + * |________________________________| + */ +void __mpa_div_q_r(mpanum q, + mpanum r, + const mpanum op1, const mpanum op2, mpa_scratch_mem pool) +{ + int q_sign; + int cmp; + + if (__mpanum_is_zero(op1)) { + mpa_set_word(q, 0); + mpa_set_word(r, 0); + return; + } + if (__mpanum_is_zero(op2)) { +#if defined(DEBUG) + DPRINT("You are trying to divide by zero. Shame on you.\n"); +#else + /* generate a divide by zero error */ + q_sign = 42 / op2->size; +#endif + return; + } + + q_sign = + (__mpanum_sign(op1) != + __mpanum_sign(op2)) ? MPA_NEG_SIGN : MPA_POS_SIGN; + cmp = __mpa_abs_cmp(op1, op2); + if (cmp == 0) { + mpa_set_word(q, 1); + mpa_set_word(r, 0); + return; + } + if (cmp > 0) { /* |op1| > |op2| */ + if (__mpanum_size(op2) > 1) + __mpa_div_q_r_internal(q, r, op1, op2, pool); + else + __mpa_div_q_r_internal_word(q, r, op1, op2->d[0]); + } else { /* |op1| < |op2| */ + mpa_set_word(q, 0); + mpa_copy(r, op1); + return; + } + __mpanum_set_sign(q, q_sign); + __mpanum_set_sign(r, __mpanum_sign(op1)); +} + +/************************************************************* + * + * LIB FUNCTIONS + * + *************************************************************/ + +/* -------------------------------------------------------------------- + * Function: mpa_div + * + * Returns the quotient and the remainder of op1 divided by op2. + * q and r must be distinct variables. + * This function returns q and r such that + * op1 = q*op2 + r + * where 0 <= r < |op2| + */ +void mpa_div(mpanum q, + mpanum r, const mpanum op1, const mpanum op2, mpa_scratch_mem pool) +{ + mpanum tmp_q; + mpanum tmp_r; + char mem_marker_q; + char mem_marker_r; + + MEMPOOL_MARKER(pool); + + /* handle the case when q is one of the operands or zero */ + if (q == op1 || q == op2 || q == 0) { + mpa_alloc_static_temp_var(&tmp_q, pool); + mem_marker_q = 1; + } else { + tmp_q = q; + mem_marker_q = 0; + } + + /* handle the case when r is one of the operands or zero */ + if (r == op1 || r == op2 || r == 0) { + mpa_alloc_static_temp_var(&tmp_r, pool); + mem_marker_r = 1; + } else { + tmp_r = r; + mem_marker_r = 0; + } + + __mpa_div_q_r(tmp_q, tmp_r, op1, op2, pool); + + if (q != 0) + mpa_copy(q, tmp_q); + if (mem_marker_q) + mpa_free_static_temp_var(&tmp_q, pool); + if (r != 0) + mpa_copy(r, tmp_r); + if (mem_marker_r) + mpa_free_static_temp_var(&tmp_r, pool); + MEMPOOL_SANITY_CHECK(pool); +} diff --git a/lib/libmpa/mpa_expmod.c b/lib/libmpa/mpa_expmod.c new file mode 100644 index 00000000000..5578f2bb027 --- /dev/null +++ b/lib/libmpa/mpa_expmod.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "mpa.h" + +/* + * Remove the #undef if you like debug print outs and assertions + * for this file. + */ +/*#undef DEBUG_ME */ +#include "mpa_debug.h" +#include "mpa_assert.h" + +/*------------------------------------------------------------ + * + * mpa_exp_mod + * + * Calculates dest = op1 ^ op2 mod n + * + */ +void mpa_exp_mod(mpanum dest, + const mpanum op1, + const mpanum op2, + const mpanum n, + const mpanum r_modn, + const mpanum r2_modn, + const mpa_word_t n_inv, mpa_scratch_mem pool) +{ + mpanum A; + mpanum B; + mpanum xtilde; + mpanum *ptr_a; + mpanum *ptr_b; + mpanum *swapper; + int idx; + + MEMPOOL_MARKER(pool); + + mpa_alloc_static_temp_var(&A, pool); + mpa_alloc_static_temp_var(&B, pool); + mpa_alloc_static_temp_var(&xtilde, pool); + + /* transform to Montgomery space */ + /* use internal version since xtidle is big enough */ + __mpa_montgomery_mul(xtilde, op1, r2_modn, n, n_inv); + + mpa_copy(A, r_modn); + ptr_a = &A; + ptr_b = &B; + __mpa_set_unused_digits_to_zero(A); + __mpa_set_unused_digits_to_zero(B); + for (idx = mpa_highest_bit_index(op2); idx >= 0; idx--) { + __mpa_montgomery_mul(*ptr_b, *ptr_a, *ptr_a, n, n_inv); + if (mpa_get_bit(op2, idx) == 1) { + __mpa_montgomery_mul(*ptr_a, *ptr_b, xtilde, n, n_inv); + } else { + swapper = ptr_a; + ptr_a = ptr_b; + ptr_b = swapper; + } + } + + /* transform back form Montgomery space */ + __mpa_montgomery_mul(*ptr_b, (const mpanum)&const_one, *ptr_a, + n, n_inv); + + mpa_copy(dest, *ptr_b); + + mpa_free_static_temp_var(&A, pool); + mpa_free_static_temp_var(&B, pool); + mpa_free_static_temp_var(&xtilde, pool); + + MEMPOOL_SANITY_CHECK(pool); +} diff --git a/lib/libmpa/mpa_gcd.c b/lib/libmpa/mpa_gcd.c new file mode 100644 index 00000000000..a9af37f6357 --- /dev/null +++ b/lib/libmpa/mpa_gcd.c @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "mpa.h" + +/* + * Remove the #undef if you like debug print outs and assertions + * for this file. + */ +#undef DEBUG_ME +#include "mpa_debug.h" +#include "mpa_assert.h" + +/************************************************************* + * + * HELPER FUNCTIONS + * + *************************************************************/ + +/*------------------------------------------------------------ + * + * __mpa_divby2 + * + */ +static void __mpa_divby2(mpanum op) +{ + mpa_word_t i; + /* The bit of the word which will be shifted into another word. */ + mpa_word_t rbit; + int msw_became_zero; + + if (__mpanum_is_zero(op)) + return; + + msw_became_zero = ((__mpanum_msw(op) >> 1) == 0) ? 1 : 0; + + op->d[0] = op->d[0] >> 1; + for (i = 1; i < __mpanum_size(op); i++) { + rbit = op->d[i] & 0x01; + op->d[i] = op->d[i] >> 1; + op->d[i - 1] ^= (rbit << (WORD_SIZE - 1)); + } + /* update the size of dest */ + if (__mpanum_sign(op) == MPA_NEG_SIGN) + op->size += msw_became_zero; + else + op->size -= msw_became_zero; +} + +/*------------------------------------------------------------ + * + * __mpa_mulby2 + * + */ +/* +static void __mpa_mulby2(mpanum op) +{ + mpa_word_t i; + mpa_word_t rbit; + mpa_word_t need_extra_word; + + if (__mpanum_is_zero(op)) + return; + + need_extra_word = (__mpanum_msw(op) & (1 << (WORD_SIZE - 1)))?1:0; + + if (need_extra_word) + i = __mpanum_size(op); + else + i = __mpanum_size(op) - 1; + while (i > 0) { + rbit = op->d[i-1] >> (WORD_SIZE - 1); + op->d[i] = op->d[i] << 1; + op->d[i] ^= rbit; + i--; + } + rbit = op->d[0] >> (WORD_SIZE - 1); + + if (__mpanum_sign(op) == MPA_POS_SIGN) + op->size += need_extra_word; + else + op->size -= need_extra_word; +} +*/ + +/* -------------------------------------------------------------------- + * Function: __mpa_egcd + * + * Given non-negative integers x and y where y < x, we compute + * gcd, a and b such that + * a*x + b*y = gcd + * + * gcd must be distrinct and non-zero, that is, + * it cannot point to the same mpanum as x_in or y_in or be a null pointer. + */ +static void __mpa_egcd(mpanum gcd, + mpanum a, + mpanum b, + const mpanum x_in, + const mpanum y_in, mpa_scratch_mem pool) +{ + mpanum A; + mpanum B; + mpanum C; + mpanum D; + mpanum x; + mpanum y; + mpanum u; + mpa_word_t k; + + MEMPOOL_MARKER(pool); + + /* have y < x from assumption */ + if (__mpanum_is_zero(y_in)) { + if (a != 0) + mpa_set_word(a, 1); + if (b != 0) + mpa_set_word(b, 0); + mpa_copy(gcd, x_in); + return; + } + mpa_alloc_static_temp_var(&x, pool); + mpa_copy(x, x_in); + mpa_alloc_static_temp_var(&y, pool); + mpa_copy(y, y_in); + + k = 0; + while (mpa_is_even(x) && mpa_is_even(y)) { + k++; + __mpa_divby2(x); + __mpa_divby2(y); + } + + mpa_alloc_static_temp_var(&u, pool); + mpa_copy(u, x); + mpa_copy(gcd, y); + mpa_alloc_static_temp_var(&A, pool); + mpa_set_word(A, 1); + mpa_alloc_static_temp_var(&B, pool); + mpa_set_word(B, 0); + mpa_alloc_static_temp_var(&C, pool); + mpa_set_word(C, 0); + mpa_alloc_static_temp_var(&D, pool); + mpa_set_word(D, 1); + + while (!__mpanum_is_zero(u)) { + while (mpa_is_even(u)) { + __mpa_divby2(u); + if (mpa_is_odd(A) || mpa_is_odd(B)) { + mpa_add(A, A, y, pool); + mpa_sub(B, B, x, pool); + } + __mpa_divby2(A); + __mpa_divby2(B); + } + + while (mpa_is_even(gcd)) { + __mpa_divby2(gcd); + if (mpa_is_odd(C) || mpa_is_odd(D)) { + mpa_add(C, C, y, pool); + mpa_sub(D, D, x, pool); + } + __mpa_divby2(C); + __mpa_divby2(D); + } + + if (mpa_cmp(u, gcd) >= 0) { + mpa_sub(u, u, gcd, pool); + mpa_sub(A, A, C, pool); + mpa_sub(B, B, D, pool); + } else { + mpa_sub(gcd, gcd, u, pool); + mpa_sub(C, C, A, pool); + mpa_sub(D, D, B, pool); + } + } + + /* copy results */ + if (a != 0) + mpa_copy(a, C); + if (b != 0) + mpa_copy(b, D); + mpa_shift_left(gcd, gcd, k); + + mpa_free_static_temp_var(&A, pool); + mpa_free_static_temp_var(&B, pool); + mpa_free_static_temp_var(&C, pool); + mpa_free_static_temp_var(&D, pool); + mpa_free_static_temp_var(&x, pool); + mpa_free_static_temp_var(&y, pool); + mpa_free_static_temp_var(&u, pool); + + MEMPOOL_SANITY_CHECK(pool); +} + +/* -------------------------------------------------------------------- + * Function: __mpa_gcd + * Computes the gcd of x and y where y <= x. + * Destination variable gcd must be allocated. + */ +static void __mpa_gcd(mpanum gcd, + const mpanum x_in, + const mpanum y_in, mpa_scratch_mem pool) +{ + mpanum x; + mpanum y; + mpanum t; + mpa_word_t k; + + MEMPOOL_MARKER(pool); + + /* have y < x from assumption */ + if (__mpanum_is_zero(y_in)) { + mpa_copy(gcd, x_in); + return; + } + mpa_alloc_static_temp_var(&x, pool); + mpa_copy(x, x_in); + mpa_alloc_static_temp_var(&y, pool); + mpa_copy(y, y_in); + + k = 0; + while (mpa_is_even(x) && mpa_is_even(y)) { + k++; + __mpa_divby2(x); + __mpa_divby2(y); + } + + mpa_alloc_static_temp_var(&t, pool); + while (!__mpanum_is_zero(x)) { + while (mpa_is_even(x)) + __mpa_divby2(x); + + while (mpa_is_even(y)) + __mpa_divby2(y); + + mpa_sub(t, x, y, pool); + /* abs val of t */ + __mpanum_set_sign(t, MPA_POS_SIGN); + __mpa_divby2(t); + if (mpa_cmp(x, y) >= 0) + mpa_copy(x, t); + else + mpa_copy(y, t); + } + + mpa_shift_left(gcd, y, k); + mpa_free_static_temp_var(&t, pool); + mpa_free_static_temp_var(&x, pool); + mpa_free_static_temp_var(&y, pool); + + MEMPOOL_SANITY_CHECK(pool); +} + +/************************************************************* + * + * LIB FUNCTIONS + * + *************************************************************/ + +/* -------------------------------------------------------------------- + * Function: mpa_gcd + * + * Computes the GCD of src1 and src2 + */ +void mpa_gcd(mpanum dest, + const mpanum src1, const mpanum src2, mpa_scratch_mem pool) +{ + int cmp; + int sign1; + int sign2; + + MEMPOOL_MARKER(pool); + + /* remember sign and take abs value */ + sign1 = __mpanum_sign(src1); + sign2 = __mpanum_sign(src2); + __mpanum_set_sign(src1, MPA_POS_SIGN); + __mpanum_set_sign(src2, MPA_POS_SIGN); + + cmp = mpa_cmp(src1, src2); + if (cmp == 0) { + mpa_copy(dest, src1); + goto cleanup; + } + if (cmp < 0) { /* src1 < src2, swap data */ + __mpa_gcd(dest, src2, src1, pool); + } else { + __mpa_gcd(dest, src1, src2, pool); + } + +cleanup: + /* restore sign */ + __mpanum_set_sign(src1, sign1); + __mpanum_set_sign(src2, sign2); + MEMPOOL_SANITY_CHECK(pool); +} + +/* -------------------------------------------------------------------- + * Function: mpa_extended_gcd + * + * Computes gcd, dest1 and dest2 such that + * dest1*src1 + dest2*src2 = gcd + * + * May be called with gcd, dest1 and/or dest2 == 0. + * + */ +void mpa_extended_gcd(mpanum gcd, + mpanum dest1, + mpanum dest2, + const mpanum src1, + const mpanum src2, mpa_scratch_mem pool) +{ + int cmp; + int sign1; + int sign2; + int mem_marker; + mpanum tmp_gcd; + + MEMPOOL_MARKER(pool); + + if (dest1 == 0 && dest2 == 0) { + if (gcd != 0) + mpa_gcd(gcd, src1, src2, pool); + return; + } + + /* remember sign and take abs value */ + sign1 = __mpanum_sign(src1); + sign2 = __mpanum_sign(src2); + __mpanum_set_sign(src1, MPA_POS_SIGN); + __mpanum_set_sign(src2, MPA_POS_SIGN); + + cmp = mpa_cmp(src1, src2); + if (cmp == 0) { + if (gcd != 0) + mpa_copy(gcd, src1); + if (dest1 != 0) + mpa_set_word(dest1, 1); + if (dest2 != 0) + mpa_set_word(dest2, 0); + goto cleanup; + } + + mem_marker = (gcd == 0 || gcd == src1 || gcd == src2); + if (mem_marker) + mpa_alloc_static_temp_var(&tmp_gcd, pool); + else + tmp_gcd = gcd; + + if (cmp < 0) /* src1 < src2, swap data */ + __mpa_egcd(tmp_gcd, dest2, dest1, src2, src1, pool); + else + __mpa_egcd(tmp_gcd, dest1, dest2, src1, src2, pool); + + if (gcd != 0) + mpa_copy(gcd, tmp_gcd); + if (mem_marker) + mpa_free_static_temp_var(&tmp_gcd, pool); + MEMPOOL_SANITY_CHECK(pool); + +cleanup: + /* restore sign */ + __mpanum_set_sign(src1, sign1); + __mpanum_set_sign(src2, sign2); + /* change resulting signs if needed */ + if (sign1 == MPA_NEG_SIGN && dest1 != 0) + __mpanum_neg(dest1); + if (sign2 == MPA_NEG_SIGN && dest2 != 0) + __mpanum_neg(dest2); +} diff --git a/lib/libmpa/mpa_init.c b/lib/libmpa/mpa_init.c new file mode 100644 index 00000000000..ac2f41e1b41 --- /dev/null +++ b/lib/libmpa/mpa_init.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "mpa.h" + +/* + * Remove the #undef if you like debug print outs and assertions + * for this file. + */ +/*#undef DEBUG_ME */ +#include "mpa_debug.h" +#include "mpa_assert.h" + +/* + * mpa_init_static + */ +void mpa_init_static(mpanum src, uint32_t len) +{ + src->alloc = U32_TO_ASIZE(len - MPA_NUMBASE_METADATA_SIZE_IN_U32); + src->size = 0; + if (src->alloc > 0) + src->d[0] = 0; +} + +/*------------------------------------------------------------ + * + * mpa_InitStaticFMMContext + * + */ +void mpa_init_static_fmm_context(mpa_fmm_context_base *context, uint32_t len) +{ + mpa_asize_t m_alloc; + + m_alloc = + U32_TO_ASIZE((mpa_asize_t) len - + (mpa_asize_t) MPA_FMM_CONTEXT_METADATA_SIZE_IN_U32); + /* clear the array before halfing into r and r2 */ + mpa_memset(context->m, 0, m_alloc * BYTES_PER_WORD); + m_alloc /= 2; + + /* setup context content */ + context->n_inv = 0; + + context->r_ptr = (void *)context->m; + context->r_ptr->alloc = + m_alloc - U32_TO_ASIZE(MPA_NUMBASE_METADATA_SIZE_IN_U32); + context->r_ptr->size = 0; + + context->r2_ptr = (mpa_num_base *)(context->m + m_alloc); + context->r2_ptr->alloc = + m_alloc - U32_TO_ASIZE(MPA_NUMBASE_METADATA_SIZE_IN_U32); + context->r2_ptr->size = 0; +} diff --git a/lib/libmpa/mpa_io.c b/lib/libmpa/mpa_io.c new file mode 100644 index 00000000000..872bca41e31 --- /dev/null +++ b/lib/libmpa/mpa_io.c @@ -0,0 +1,626 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "mpa.h" + +/* + * Big #ifdef to get rid of string conversion routines + */ +#if defined(MPA_INCLUDE_STRING_CONVERSION) + +/* + * Remove the #undef if you like debug print outs and assertions + * for this file. + */ +/*#undef DEBUG_ME */ +#include "mpa_debug.h" +#include "mpa_assert.h" + +/************************************************************* + * + * HELPERS + * + *************************************************************/ + +/* -------------------------------------------------------------------- + * Function: __mpa_isspace + * + * Returns 1 if c is a while space character + */ +static int __mpa_isspace(char c) +{ + return c == '_' || /* allow underscore which makes long hex */ + /* numbers easier to read */ + c == ' ' || /* space */ + c == '\n' || /* new line */ + c == '\r' || /* carriage return */ + c == '\t'; /* tab */ +} + +/* -------------------------------------------------------------------- + * Function: __mpa_is_char_in_base + * + * Returns 1 if c is either a white space char or a char in the current base, + * and 0 otherwise. + */ +static int __mpa_is_char_in_base(int base, int c) +{ + if (__mpa_isspace(c)) + return 1; + + switch (base) { + case 10: + return (c >= '0') && (c <= '9'); + case 16: + return ((c >= '0') && (c <= '9')) || + ((c >= 'A') && (c <= 'F')) || + ((c >= 'a') && (c <= 'f')); + default: + return 0; + } +} + +/* -------------------------------------------------------------------- + * Function: __mpa_digit_value + * + * Returns the integer value of the hexadecimal character c. + */ +static int __mpa_digit_value(int c) +{ + if ((c >= '0') && (c <= '9')) + return c - '0'; + if ((c >= 'A') && (c <= 'F')) + return c - 'A' + 10; + if ((c >= 'a') && (c <= 'f')) + return c - 'a' + 10; + + /* defensive */ + return 0; +} + +/* -------------------------------------------------------------------- + * Function: __mpa_digitstr_to_binary_wsize + * + * Returns the maximum number of words needed to binary represent a number + * consisting of "digits" digits and each digits is in base "base". + */ +static mpa_word_t __mpa_digitstr_to_binary_wsize(int base, int digits) +{ + switch (base) { + case 10: + return (mpa_word_t) ((3.4 * digits) + (WORD_SIZE - 1)) >> + LOG_OF_WORD_SIZE; + case 16: + return (digits + 7) >> 3; + default: + return 0; + } +} + +/* -------------------------------------------------------------------- + * Function: __mpa_nibble_to_char + * + * caseing = 1 is lower case, 0 is uppercase + */ +static char __mpa_nibble_to_char(mpa_word_t c, int caseing) +{ + c &= 0xf; + if (c < 0xa) + return '0' + (char)c; + return caseing == 0 ? 'A' - 0xA + (char)c: 'a' - 0xa + (char)c; +} + +/* -------------------------------------------------------------------- + * Function: __mpa_word_to_hexstr + * + * caseing 8= 1 is lower case, 0 is uppercase + */ +static void __mpa_word_to_hexstr(char *str, mpa_word_t w, int caseing) +{ + int i; + for (i = NIBBLES_PER_WORD; i > 0; i--) { + str[i - 1] = + __mpa_nibble_to_char(NIBBLE_OF_WORD(i - 1, w), caseing); + } +} + +/* -------------------------------------------------------------------- + * Function: __mpa_mpanum_to_hexstr + * + * caseing = 1 is lower case, 0 is uppercase + */ +static int __mpa_mpanum_to_hexstr(char *str, int caseing, const mpanum n) +{ + int d_idx; + char digits[NIBBLES_PER_WORD]; + int i; + char *cptr; + int hex_digits; + + /* get high word with data in, watch out for zero case */ + d_idx = __mpanum_size(n); + if (d_idx == 0) { + *str++ = '0'; + *str = '\0'; + return 1; + } + d_idx--; + + cptr = str; + + /* the msw is special, since if we should not print leading zeros. + */ + __mpa_word_to_hexstr(digits, n->d[d_idx], caseing); + + /* find the left-most non-zero digit */ + i = NIBBLES_PER_WORD; + while (i-- > 0) + if (digits[i] != '0') + break; + while (i >= 0) + *str++ = digits[i--]; + + /* convert each word to a hex string */ + d_idx--; + while (d_idx >= 0) { + __mpa_word_to_hexstr(digits, n->d[d_idx], caseing); + i = NIBBLES_PER_WORD - 1; + while (i >= 0) + *str++ = digits[i--]; + d_idx--; + } + hex_digits = (int)(str - cptr); + *str++ = '\0'; + return hex_digits; +} + +/* -------------------------------------------------------------------- + * Function: __mpa_count_leading_zero_bits + * + * + */ +static mpa_word_t __mpa_count_leading_zero_bits(mpa_word_t w) +{ + mpa_word_t mask; + mpa_word_t zeros; + + if (w == 0) + return MPA_WORD_SIZE; + mask = (1 << (MPA_WORD_SIZE - 1)); + zeros = 0; + while (!(w & mask)) { + zeros++; + mask >>= 1; + } + return zeros; +} + +/* -------------------------------------------------------------------- + * Function: mpa_SizeInBase + * + * Returns the number of characters needed to print |n| in base "base". + * base can be 16, 10 or 2. + */ +static mpa_word_t __mpa_size_in_base(const mpanum n, int base) +{ + mpa_word_t totalbits; + /* number of leading zero bits in the msw of n */ + mpa_word_t zerobits_msw; + + if (__mpanum_is_zero(n)) + return 1; + + zerobits_msw = __mpa_count_leading_zero_bits( + n->d[__mpanum_size(n) - 1]); + totalbits = WORD_SIZE * __mpanum_size(n) - zerobits_msw; + + switch (base) { + case UINT8_MAX: + return (totalbits + 7) / 8; + case 16: + return (totalbits + 3) / 4; + case 10: + /* 1/log2(10) */ + return (mpa_word_t) (totalbits * 0.3010299956639811) + 1; + default: + return totalbits; + } +} + +/* -------------------------------------------------------------------- + * Function: __mpa_add_grouping + * + * Adds grouping and pad left with zeros up to groupsize chars + * src_len is length of src without the terminating '\0'. + * It will add a terminating '\0' to dest. + */ +static void __mpa_add_grouping(char *dest, + const char *src, int src_len, int groupsize) +{ + int grppos; + const char *endptr; + + if (!(groupsize > 0)) { + DPRINT("Groupsize is zero or negative. Cannot do grouping.\n"); + return; + } + + if (src_len <= 0) { + while (groupsize--) + *dest++ = '0'; + *dest++ = '\0'; + return; + } + endptr = src + src_len; + if (src_len % groupsize != 0) { + /* + * Digits cannot be evenly divided into groups of the right + * size. + */ + + grppos = (groupsize - (src_len % groupsize)) % groupsize; + while (grppos--) + *dest++ = '0'; + grppos = (src_len % groupsize); + while (grppos--) + *dest++ = *src++; + + /* insert first space */ + if (src < endptr) + *dest++ = ' '; + } + grppos = groupsize; + while (src < endptr) { + *dest++ = *src++; + grppos--; + if (grppos == 0 && src < endptr) { + *dest++ = ' '; + grppos = groupsize; + } + } + + /* terminate dest */ + *dest++ = '\0'; +} + +/* -------------------------------------------------------------------- + * Function: mpa_get_str_size + * + * Return the max size of the string representing a Big Number + */ +int mpa_get_str_size(void) +{ + return MPA_STR_MAX_SIZE; +} + +/************************************************************* + * + * LIB FUNCTIONS + * + *************************************************************/ + +/* -------------------------------------------------------------------- + * Function: mpa_set_str + * + * Assigns dest the value of the digitstr, where digitstr is a character + * string. + * If the digitstr starts with a valid number, the valid part will be + * converted and the rest of the digitstr will not be parsed further. + * digitstr is assumed to be in base 16. + * Returns -1 if the digitstr was malformed, and the number of base digits + * converted (not including leading zeros) if the conversion was OK. + * If the digitstr is a null-ptr we return -1. + * If the digitstr is empty, we don't touch dest and just returns 0. + * If the digitstr only consists of white spaces, we set dest to zero + * returns 0. + */ +int mpa_set_str(mpanum dest, const char *digitstr) +{ + /* length of digitstr after removal of base indicator and spaces */ + int dlen; + int negative; /* ==1 if number is negative, 0 otherwise */ + int c; /* value of characters in digitstr */ + /* a buffer holding the integer values of the digits */ + static unsigned char buf[MPA_STR_MAX_SIZE]; + /* number of digits in digitstr which has been place in buf */ + int bufidx; + const char *endp; /* points to the end of digitstr */ + int retval; + /* + * Pointer intto dest->d where we should put the next word during + * conversion. + */ + mpa_word_t *w; + int i; /* loop variable */ + + /* some basic sanity checks first */ + if (*digitstr == 0) { + DPRINT("digitstr was empty, leaving dest unchanged\n"); + return 0; + } + + /* remove leading spaces */ + do { + c = (unsigned char)*digitstr++; + } while (__mpa_isspace(c)); + + /* check negative sign */ + negative = 0; + if (c == '-') { + negative = 1; + c = (unsigned char)*digitstr++; + } + if (c == '\0') { + DPRINT("digitstr consisted of only white spaces and possibly a single '-' sign. Setting dest to zero\n"); + mpa_set_word(dest, 0); + return 0; + } + + /* see if we have a '0x' prefix */ + if (c == '0') { + c = (unsigned char)*digitstr++; + if (c == 'x' || c == 'X') + c = (unsigned char)*digitstr++; + } + + /* skip leading zeros and spaces */ + while (c == '0' || __mpa_isspace(c)) + c = (unsigned char)*digitstr++; + + /* check if we had a simple "0" string */ + if (c == '\0') { + mpa_set_word(dest, 0); + return 0; + } + + /* find the end of digitstr */ + endp = digitstr; + while (*endp != 0) + endp++; + + /* + 1 since we have one character in 'c' */ + dlen = (int)(endp - digitstr) + 1; + ASSERT(dlen <= MPA_STR_MAX_SIZE, "String max size is too small"); + /* convert to a buffer of bytes */ + bufidx = 0; + while (__mpa_is_char_in_base(16, c)) { + if (!__mpa_isspace(c)) + buf[bufidx++] = __mpa_digit_value(c); + c = (unsigned char)*digitstr++; + } + + if (bufidx == 0) { + retval = -1; + goto cleanup; + } + + ASSERT((__mpa_digitstr_to_binary_wsize(16, bufidx) <= + __mpanum_alloced(dest)), "Dest is too small."); + + retval = bufidx; + w = dest->d; + mpa_set_word(dest, 0); + /* start converting */ + *w = 0; + i = BYTES_PER_WORD; + dest->size = 1; + bufidx--; /* dec to get inside buf range */ + while (bufidx > 1) { + *w ^= + (((buf[bufidx - 1] << 4) ^ (buf[bufidx])) << + ((BYTES_PER_WORD - i) << 3)); + i--; + bufidx -= 2; + if (i == 0) { + w++; + *w = 0; + i = BYTES_PER_WORD; + dest->size++; + } + } + if (bufidx == 1) + *w ^= + (((buf[bufidx - 1] << 4) ^ (buf[bufidx])) << + ((BYTES_PER_WORD - i) << 3)); + if (bufidx == 0) + *w ^= (buf[bufidx] << ((BYTES_PER_WORD - i) << 3)); + + if (negative) + __mpanum_neg(dest); + +cleanup: + return retval; +} + +/* -------------------------------------------------------------------- + * Function: mpa_get_str + * + * Prints a representation of n into str. + * The length allocated is the space needed to print n plus additional + * chars for the minus sign and the terminating '\0' char. + * If grouping is used, we allocate space to pad the number string with + * zeros to the left, up to the current group size. + * A pointer to str is returned. If something went wrong, we return 0. + * + * mode is one of the following: + * MPA_STRING_MODE_HEX_UC hex notation using upper case + * MPA_STRING_MODE_HEX_LC hex notation using lower case + * + */ +char *mpa_get_str(char *str, int mode, int groupsize, const mpanum n) +{ + char *str_to_fill; + /* internal str with only digits, and no grouping */ + static char int_str[MPA_STR_MAX_SIZE]; + int chars_written; + + ASSERT(str != 0, "str destination buffer is null"); + + if (groupsize == 0) + str_to_fill = str; + else + str_to_fill = int_str; + + /* insert a minus sign */ + if (__mpanum_sign(n) == MPA_NEG_SIGN) { + *str_to_fill = '-'; + str_to_fill++; + } + switch (mode) { + case MPA_STRING_MODE_HEX_UC: + chars_written = __mpa_mpanum_to_hexstr(str_to_fill, 0, n); + break; + case MPA_STRING_MODE_HEX_LC: + chars_written = __mpa_mpanum_to_hexstr(str_to_fill, 1, n); + break; + default: + DPRINT("Unknown mode %d\n", mode); + return 0; + } + + if (groupsize != 0) + __mpa_add_grouping(str, int_str, chars_written, groupsize); + + return str; +} + +#endif /* #if defined (MPA_INCLUDE_STRING_CONVERSION) */ + +static mpa_word_t set_word(const uint8_t *in, size_t in_len) +{ + int i; + mpa_word_t out; + + out = 0; + for (i = in_len - 1; i >= 0; i--) + out |= in[i] << ((in_len - i - 1) * 8); + return out; +} + +int mpa_set_oct_str(mpanum dest, const uint8_t *buffer, size_t buffer_len, + bool negative) +{ + const uint8_t *buf = buffer; + int bufidx = buffer_len; + mpa_word_t *w; + + /* Strip of leading zero octets */ + while (bufidx > 0) { + if (*buf != 0) + break; + bufidx--; + buf++; + } + + if (bufidx == 0) { + mpa_set_word(dest, 0); + return 0; + } + + /* + * bufidx is now indexing one byte past past the last byte in the octet + * string relative to buf. + */ + + if ((size_t) (bufidx - 1) > (BYTES_PER_WORD * __mpanum_alloced(dest))) + return -1; /* No space */ + + w = dest->d; + mpa_set_word(dest, 0); + /* start converting */ + dest->size = 0; + while (bufidx > 0) { + int l = __MIN(BYTES_PER_WORD, bufidx); + + bufidx -= l; + *w = set_word(buf + bufidx, l); + w++; + dest->size++; + } + + if (negative) + __mpanum_neg(dest); + + return 0; +} + +static void get_word(mpa_word_t in, uint8_t out[BYTES_PER_WORD]) +{ + int i; + + for (i = BYTES_PER_WORD - 1; i >= 0; i--) { + out[i] = in & UINT8_MAX; + in >>= 8; + } +} + +int mpa_get_oct_str(uint8_t *buffer, size_t *buffer_len, const mpanum n) +{ + size_t req_blen = __mpa_size_in_base(n, UINT8_MAX); + uint8_t first_word[BYTES_PER_WORD]; + size_t bufidx = 0; + int d_idx; + int i; + + if (*buffer_len < req_blen) { + *buffer_len = req_blen; + return -1; + } + /* get high word with data in, watch out for zero case */ + d_idx = __mpanum_size(n); + if (d_idx == 0) { + memset(buffer, 0, *buffer_len); + goto out; + } + d_idx--; + + /* Strip of leading zero octets */ + get_word(n->d[d_idx], first_word); + + for (i = 0; i < BYTES_PER_WORD; i++) { + if (first_word[i] != 0) { + memcpy(buffer, first_word + i, BYTES_PER_WORD - i); + bufidx = BYTES_PER_WORD - i; + break; + } + } + d_idx--; + + while (d_idx >= 0) { + if (bufidx > req_blen) + return -1; + get_word(n->d[d_idx], buffer + bufidx); + + bufidx += BYTES_PER_WORD; + d_idx--; + } + +out: + *buffer_len = req_blen; + return 0; +} + +/* end of file mpa_io.c */ diff --git a/lib/libmpa/mpa_mem_static.c b/lib/libmpa/mpa_mem_static.c new file mode 100644 index 00000000000..a9d9387d7c1 --- /dev/null +++ b/lib/libmpa/mpa_mem_static.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "mpa.h" + +/* + * Remove the #undef if you like debug print outs and assertions + * for this file. + */ +/*#undef DEBUG_ME */ +#include "mpa_debug.h" +#include "mpa_assert.h" + +/* + * mpa_init_scratch_mem + */ +void mpa_init_scratch_mem(mpa_scratch_mem pool, int nr_vars, int max_bits) +{ + /* + * Check the max size of a string + * if we support up to 'n' bits of a big number, + * that means 2^n = 2^4^(n/4) = 16^(n/4) + * Because of grouping of '1' (worst case), this has to be + * multiplied by 2 + * Because internal computation needs twice the number of bits, + * multiply by 2 + * Plus the sign + * Plus \0 at the end + * ==> (n/4)*2+1+1 ~ n+2 + */ + ASSERT(((max_bits + 2) <= mpa_get_str_size()), + "! (max_bits/4) <= mpa_get_str_size()"); + + pool->nrof_vars = nr_vars; + pool->alloc_size = mpa_StaticTempVarSizeInU32(max_bits); + pool->bit_size = max_bits; + mpa_memset(pool->m, 0, + ASIZE_TO_U32(pool->nrof_vars * pool->alloc_size) * 4); +} + +/*------------------------------------------------------------ + * + * mpa_alloc_static_temp_var + * + */ +mpanum mpa_alloc_static_temp_var(mpanum *var, mpa_scratch_mem pool) +{ + int idx; + mpa_num_base *tvar; + + idx = 0; + tvar = (void *)pool->m; + while (tvar->alloc != 0 && idx < pool->nrof_vars) { + tvar = + (void *)&pool->m[idx * + mpa_StaticTempVarSizeInU32(pool-> + bit_size)]; + idx++; + } + if ((4 < tvar->alloc) != 0) { + DPRINT("Out of temp vars. Dumping pattern : 0x%X\n", + __mpa_get_alloced_pattern(pool)); + DPRINT("TOO SMALL SCRATCH MEM AREA. THIS MUST NOT HAPPEN!\n"); + return NULL; + } + *var = tvar; + mpa_init_static(*var, mpa_StaticTempVarSizeInU32(pool->bit_size)); + return *var; +} + +/*------------------------------------------------------------ + * + * mpa_free_static_temp_var + * + */ +void mpa_free_static_temp_var(mpanum *var, mpa_scratch_mem pool) +{ + IDENTIFIER_NOT_USED(pool); + + if (*var != NULL) { + /* mark it as free */ + (*var)->alloc = 0; + } +} + +/*------------------------------------------------------------ + * + * mpa_get_alloced_pattern + * + */ +uint32_t __mpa_get_alloced_pattern(mpa_scratch_mem pool) +{ + uint32_t p; + int idx; + mpa_num_base *tvar; + + p = 0; + for (idx = 0; idx < pool->nrof_vars; idx++) { + tvar = + (void *)&pool->m[idx * + mpa_StaticTempVarSizeInU32(pool-> + bit_size)]; + if (tvar->alloc != 0) + p ^= (1 << idx); + } + return p; +} diff --git a/lib/libmpa/mpa_misc.c b/lib/libmpa/mpa_misc.c new file mode 100644 index 00000000000..cda1aba74a8 --- /dev/null +++ b/lib/libmpa/mpa_misc.c @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "mpa.h" + +/* + * Remove the #undef if you like debug print outs and assertions + * for this file. + */ +/*#undef DEBUG_ME */ +#include "mpa_debug.h" +#include "mpa_assert.h" + +/************************************************************* + * + * GLOBAL CONSTANTS + * + *************************************************************/ + +const mpa_num_base const_largest_deci_base = { + 1, 1, {LARGEST_DECIMAL_BASE_IN_WORD} }; +const mpa_num_base Const_1_LShift_Base = { 2, 2, {0, 1} }; +const mpa_num_base const_one = { 1, 1, {1} }; + +/************************************************************* + * + * HELPERS + * + *************************************************************/ + +/* -------------------------------------------------------------------- + * Function: __mpa_set_unused_digits_to_zero + * + * + */ +void __mpa_set_unused_digits_to_zero(mpanum n) +{ + int i; + + /* + * Pointer arithmetics on *mpa_word_t will put the + * pointer at the right place. + */ + i = __mpanum_size(n); + mpa_memset((n->d) + i, 0, (n->alloc - i) * BYTES_PER_WORD); +} + +/************************************************************* + * + * LIB FUNCTIONS + * + *************************************************************/ + +/*------------------------------------------------------------ + * + * mpa_wipe + * + * fills the digits with zero and set size = 0; + * + */ +void mpa_wipe(mpanum var) +{ + mpa_memset(var->d, 0, var->alloc * BYTES_PER_WORD); + var->size = 0; +} + +/*------------------------------------------------------------ + * + * mpa_copy + * + * Copies src to dest. + * + * Doesn't check if src fits into dest + * + */ +void mpa_copy(mpanum dest, const mpanum src) +{ + if (dest == src) + return; + + mpa_memcpy(dest->d, src->d, __mpanum_size(src) * BYTES_PER_WORD); + dest->size = src->size; +} + +/* -------------------------------------------------------------------- + * Function: mpa_abs + * Computes the absolut value of src and puts it in dest + * dest and src can be the same mpanum + */ +void mpa_abs(mpanum dest, const mpanum src) +{ + mpa_copy(dest, src); + __mpanum_set_sign(dest, MPA_POS_SIGN); +} + +/* -------------------------------------------------------------------- + * Function: mpa_highest_bit_index + * Returns the index of the highest 1 in |src|. + * The index starts at 0 for the least significant bit. + * If src == zero, it will return -1 + * + */ +int mpa_highest_bit_index(const mpanum src) +{ + mpa_word_t w; + mpa_word_t b; + + if (__mpanum_is_zero(src)) + return -1; + + w = __mpanum_msw(src); + + for (b = 0; b < WORD_SIZE; b++) { + w >>= 1; + if (w == 0) + break; + } + return (int)(__mpanum_size(src) - 1) * WORD_SIZE + b; +} + +/*------------------------------------------------------------ + * + * mpa_get_bit + * + * Returns the value of the idx:th bit in src. + * if idx is larger than the number of bits in src, + * it returns zero. + * + */ +uint32_t mpa_get_bit(const mpanum src, uint32_t idx) +{ + mpa_word_t w; /* word of bitIndex */ + unsigned long b; /* bit number in that word */ + + w = idx >> LOG_OF_WORD_SIZE; + b = idx & (WORD_SIZE - 1); + + if (w > __mpanum_size(src)) + return 0; + b = (1 << b); + return ((src->d[w] & b) != 0); +} + +/*------------------------------------------------------------ + * + * mpa_CanHold + * + * returns 1 if dest can hold src without overflowing, 0 otherwise + */ +int mpa_can_hold(mpanum dest, const mpanum src) +{ + return (__mpanum_alloced(dest) >= __mpanum_size(src) ? 1 : 0); +} + +/*------------------------------------------------------------ + * + * mpa_parity + * + */ +int mpa_parity(const mpanum src) +{ + return (((__mpanum_lsw(src) & 0x01) == + 0) ? MPA_EVEN_PARITY : MPA_ODD_PARITY); +} + +/*------------------------------------------------------------ + * + * mpa_constant_one + * + */ +mpanum mpa_constant_one(void) +{ + return (mpanum)&const_one; +} diff --git a/lib/libmpa/mpa_modulus.c b/lib/libmpa/mpa_modulus.c new file mode 100644 index 00000000000..f4d85daa4c9 --- /dev/null +++ b/lib/libmpa/mpa_modulus.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "mpa.h" + +/* + * Remove the #undef if you like debug print outs and assertions + * for this file. + */ +/*#undef DEBUG_ME */ +#include "mpa_debug.h" +#include "mpa_assert.h" + +/************************************************************* + * + * LIB FUNCTIONS + * + *************************************************************/ + +/*------------------------------------------------------------ + * + * mpa_mod + * + */ +void mpa_mod(mpanum dest, const mpanum op, const mpanum n, mpa_scratch_mem pool) +{ + MEMPOOL_MARKER(pool); + + mpa_div(NULL, dest, op, n, pool); + + MEMPOOL_SANITY_CHECK(pool); +} + +/*------------------------------------------------------------ + * + * mpa_add_mod + * + */ +void mpa_add_mod(mpanum dest, + const mpanum op1, + const mpanum op2, const mpanum n, mpa_scratch_mem pool) +{ + mpanum tmp_dest; + + MEMPOOL_MARKER(pool); + + mpa_alloc_static_temp_var(&tmp_dest, pool); + + mpa_add(tmp_dest, op1, op2, pool); + mpa_div(NULL, dest, tmp_dest, n, pool); + + mpa_free_static_temp_var(&tmp_dest, pool); + MEMPOOL_SANITY_CHECK(pool); +} + +/*------------------------------------------------------------ + * + * mpa_sub_mod + * + */ +void mpa_sub_mod(mpanum dest, + const mpanum op1, + const mpanum op2, const mpanum n, mpa_scratch_mem pool) +{ + mpanum tmp_dest; + + MEMPOOL_MARKER(pool); + + mpa_alloc_static_temp_var(&tmp_dest, pool); + + mpa_sub(tmp_dest, op1, op2, pool); + mpa_div(NULL, dest, tmp_dest, n, pool); + + mpa_free_static_temp_var(&tmp_dest, pool); + + MEMPOOL_SANITY_CHECK(pool); +} + +/*------------------------------------------------------------ + * + * mpa_mul_mod + * + */ +void mpa_mul_mod(mpanum dest, + const mpanum op1, + const mpanum op2, const mpanum n, mpa_scratch_mem pool) +{ + mpanum tmp_dest; + + MEMPOOL_MARKER(pool); + + mpa_alloc_static_temp_var(&tmp_dest, pool); + + mpa_mul(tmp_dest, op1, op2, pool); + mpa_div(NULL, dest, tmp_dest, n, pool); + + mpa_free_static_temp_var(&tmp_dest, pool); + + MEMPOOL_SANITY_CHECK(pool); +} + +/*------------------------------------------------------------ + * + * mpa_inv_mod + * + */ +int mpa_inv_mod(mpanum dest, + const mpanum op, const mpanum n, mpa_scratch_mem pool) +{ + mpanum gcd; + mpanum tmp_dest; + int mem_marker; + int res; + + MEMPOOL_MARKER(pool); + + if (mpa_cmp_short(op, 1) == 0) { + mpa_set_S32(dest, 1); + return 0; + } + + mem_marker = (dest == op); + if (mem_marker) + mpa_alloc_static_temp_var(&tmp_dest, pool); + else + tmp_dest = dest; + + mpa_alloc_static_temp_var(&gcd, pool); + /* The function mpa_extended_gcd behaves badly if tmp_dest = op */ + mpa_extended_gcd(gcd, tmp_dest, NULL, op, n, pool); + res = mpa_cmp_short(gcd, 1); + + if (mem_marker) { + mpa_copy(dest, tmp_dest); + mpa_free_static_temp_var(&tmp_dest, pool); + } + + mpa_free_static_temp_var(&gcd, pool); + MEMPOOL_SANITY_CHECK(pool); + + if (res == 0) { + while (mpa_cmp_short(dest, 0) < 0) + mpa_add(dest, dest, n, pool); + return 0; + } else { + return -1; + } +} diff --git a/lib/libmpa/mpa_montgomery.c b/lib/libmpa/mpa_montgomery.c new file mode 100644 index 00000000000..26b756afc76 --- /dev/null +++ b/lib/libmpa/mpa_montgomery.c @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "mpa.h" + +/* + * Remove the #undef if you like debug print outs and assertions + * for this file. + */ +#undef DEBUG_ME +#include "mpa_debug.h" +#include "mpa_assert.h" + +/************************************************************* + * + * HELPERS + * + *************************************************************/ + +/*------------------------------------------------------------ + * + * These functions have ARM assembler implementations + * + */ +#if !defined(USE_ARM_ASM) + +/* -------------------------------------------------------------------- + * Function: __mpa_montgomery_mul_add + * Calculates dest = dest + src*w + * Dest must be big enough to hold the result + */ +void __mpa_montgomery_mul_add(mpanum dest, mpanum src, mpa_word_t w) +{ +#if defined(MPA_SUPPORT_DWORD_T) + mpa_dword_t a; + mpa_word_t *ddig; + int32_t idx; + mpa_word_t carry; + mpa_word_t *dest_begin; + + if (w == 0) + return; + dest_begin = dest->d; + ddig = dest->d; + carry = 0; + for (idx = 0; idx < src->size; idx++) { + a = (mpa_dword_t) *ddig + + (mpa_dword_t) src->d[idx] * (mpa_dword_t) w + + (mpa_dword_t) (carry); + *(ddig++) = (mpa_word_t) (a); + carry = (mpa_word_t) (a >> WORD_SIZE); + } + while (carry) { + a = (mpa_dword_t) (*ddig) + (mpa_dword_t) (carry); + *(ddig++) = (mpa_word_t) (a); + carry = (mpa_word_t) (a >> WORD_SIZE); + } + idx = (mpa_word_t) (ddig - dest_begin); + if (idx > dest->size) + dest->size = idx; + +#else +#error write non-dword code for __mpa_montgomery_mul_add +#endif +} + +/* -------------------------------------------------------------------- + * Function: __mpa_montgomery_sub_ack + * Calculates dest = dest - src + * Assumption: dest >= src and both non-negative + * and dest > src. + * + */ +void __mpa_montgomery_sub_ack(mpanum dest, mpanum src) +{ +#if defined(MPA_SUPPORT_DWORD_T) + mpa_word_t *ddig; + mpa_word_t carry; + int32_t idx; + mpa_dword_t a; + + ddig = dest->d; + carry = 0; + idx = 0; + while (idx < src->size) { + a = (mpa_dword_t) (*ddig) - (mpa_dword_t) src->d[idx] - + (mpa_dword_t) carry; + *(ddig++) = (mpa_word_t) (a); + carry = 0 - (mpa_word_t) (a >> WORD_SIZE); + idx++; + } + /* Here we have no more digits in op2, we only need to keep on + * subtracting 0 from op1, and deal with carry */ + while (carry) { + a = (mpa_dword_t) (*ddig) - (mpa_dword_t) carry; + *(ddig++) = (mpa_word_t) (a); + carry = 0 - (mpa_word_t) (a >> WORD_SIZE); + idx++; + } + if (idx >= dest->size) { + /* carry did propagate all the way, fix size */ + while (dest->size > 0 && *(--ddig) == 0) + dest->size--; + } +#else +#error write non-dword code for __mpa_montgomery_sub_ack +#endif +} + +#endif /* USE_ARM_ASM */ + +/*------------------------------------------------------------ + * + * __mpa_montgomery_mul + * + * NOTE: + * Dest need to be able to hold one more word than the size of n + * + */ +void __mpa_montgomery_mul(mpanum dest, mpanum op1, mpanum op2, mpanum n, + mpa_word_t n_inv) +{ + mpa_word_t u; + mpa_usize_t idx; + + /* set dest to zero (with all unused digits to zero as well) */ + mpa_wipe(dest); + + for (idx = 0; idx < n->size; idx++) { + u = (dest->d[0] + + __mpanum_get_word(idx, op1) * + __mpanum_get_word(0, op2)) * n_inv; + + __mpa_montgomery_mul_add(dest, op2, + __mpanum_get_word(idx, op1)); + __mpa_montgomery_mul_add(dest, n, u); + + /* Shift right one mpa_word */ + dest->size--; + for (mpa_usize_t i = 0; i < dest->size; i++) + dest->d[i] = dest->d[i + 1]; + *(dest->d + dest->size) = 0; /* set unused digit to zero. */ + } + + /* check if dest > n, if so set dest = dest - n */ + if (__mpa_abs_cmp(dest, n) >= 0) + __mpa_montgomery_sub_ack(dest, n); +} + +/************************************************************* + * + * LIB FUNCTIONS + * + *************************************************************/ + +/* + * mpa_compute_fmm_context + */ +int mpa_compute_fmm_context(const mpanum modulus, + mpanum r_modn, + mpanum r2_modn, + mpa_word_t *n_inv, + mpa_scratch_mem pool) +{ + mpa_usize_t s; + int cmpresult; + mpanum tmp_n_inv; + mpanum gcd; + + MEMPOOL_MARKER(pool); + + /* create a small mpanum on the stack */ + uint32_t n_lsw_u32[MPA_NUMBASE_METADATA_SIZE_IN_U32 + ASIZE_TO_U32(1)]; + mpanum n_lsw = (mpa_num_base *)&n_lsw_u32; + + /* + * compute r to be + * 1 << (__mpanum_size(Modulus) * WORD_SIZE) mod modulus + */ + s = __mpanum_size(modulus); + mpa_set_word(r_modn, 1); + mpa_shift_left(r_modn, r_modn, s * WORD_SIZE); + mpa_mod(r_modn, r_modn, modulus, pool); + + /* compute r^2 mod modulus */ + mpa_mul_mod(r2_modn, r_modn, r_modn, modulus, pool); + + /* Compute the inverse of modulus mod 1 << WORD_SIZE */ + n_lsw->alloc = 1; + n_lsw->size = 1; + n_lsw->d[0] = __mpanum_lsw(modulus); + + mpa_alloc_static_temp_var(&tmp_n_inv, pool); + mpa_alloc_static_temp_var(&gcd, pool); + + mpa_extended_gcd(gcd, tmp_n_inv, NULL, n_lsw, + (const mpanum)&Const_1_LShift_Base, pool); + cmpresult = mpa_cmp_short(gcd, 1); + + if (cmpresult != 0) + goto cleanup; + + /* + * We need the number n' (n_inv) such that + * + * R*r' - N*n' == 1 + * + * and Extended_GCD gives us the solution to + * + * R*r' + N*n' == 1 + * + * So if n' is negative, we just forget about the sign. + * If n' is positive, we need to subtract R to get + * the right residue class. + */ + if (__mpanum_sign(tmp_n_inv) == MPA_POS_SIGN) { + mpa_sub(tmp_n_inv, tmp_n_inv, + (const mpanum)&Const_1_LShift_Base, pool); + } + /* then take the absolute value */ + *n_inv = __mpanum_lsw(tmp_n_inv); + +cleanup: + + mpa_free_static_temp_var(&gcd, pool); + mpa_free_static_temp_var(&tmp_n_inv, pool); + + MEMPOOL_SANITY_CHECK(pool); + + if (cmpresult != 0) + return -1; + return 0; +} + +/*------------------------------------------------------------ + * + * mpa_montgomery_mul + * + * wrapper that uses a temp variables for dest, since + * that need to be one word larger that n. + */ +void mpa_montgomery_mul(mpanum dest, + mpanum op1, + mpanum op2, + mpanum n, mpa_word_t n_inv, mpa_scratch_mem pool) +{ + mpanum tmp_dest; + + MEMPOOL_MARKER(pool); + + mpa_alloc_static_temp_var(&tmp_dest, pool); + + __mpa_montgomery_mul(tmp_dest, op1, op2, n, n_inv); + + mpa_copy(dest, tmp_dest); + mpa_free_static_temp_var(&tmp_dest, pool); + + MEMPOOL_SANITY_CHECK(pool); +} diff --git a/lib/libmpa/mpa_mul.c b/lib/libmpa/mpa_mul.c new file mode 100644 index 00000000000..49767d9a5f8 --- /dev/null +++ b/lib/libmpa/mpa_mul.c @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "mpa.h" + +/* + * Remove the #undef if you like debug print outs and assertions + * for this file. + */ +/*#undef DEBUG_ME */ +#include "mpa_debug.h" +#include "mpa_assert.h" + +/************************************************************* + * + * HELPERS + * + *************************************************************/ + +/*------------------------------------------------------------ + * + * These functions have ARM assembler implementations + * + */ +#if !defined(USE_ARM_ASM) + +/* -------------------------------------------------------------------- + * Function: __mpa_mul_add_word + * + * Multiplies a and b and adds the incoming carry to produce the product p + * outgoing carry is stored in *carry. + */ +void __mpa_mul_add_word(mpa_word_t a, + mpa_word_t b, mpa_word_t *p, mpa_word_t *carry) +{ +#if defined(MPA_SUPPORT_DWORD_T) + mpa_dword_t prod; + + prod = (mpa_dword_t) (a) * (mpa_dword_t) (b) + (mpa_dword_t) (*carry); + *p = (mpa_word_t) prod; + *carry = (mpa_word_t) (prod >> MPA_WORD_SIZE); +#else +#error "error, write non-dword_t code for __mpa_mul_add_word" +#endif +} + +/* -------------------------------------------------------------------- + * Function: __mpa_mul_add_word_cum + * + * Multiplies a and b and adds the incoming carry and the cumulative + * product stored in *p. + * Outgoing carry is stored in *carry. + */ +void __mpa_mul_add_word_cum(mpa_word_t a, + mpa_word_t b, mpa_word_t *p, mpa_word_t *carry) +{ +#if defined(MPA_SUPPORT_DWORD_T) + mpa_dword_t prod; + + prod = + (mpa_dword_t) (a) * (mpa_dword_t) (b) + (mpa_dword_t) (*p) + + (mpa_dword_t) (*carry); + *p = (mpa_word_t) prod; + *carry = (mpa_word_t) (prod >> MPA_WORD_SIZE); +#else +#error "error: write non-dword_t code for __mpa_mul_add_word_cum" +#endif +} + +#endif /* USE_ARM_ASM */ + +/* -------------------------------------------------------------------- + * Function: __mpa_abs_mul_word + * + * Simpler multiplication when one operand is known to be a word. + * Calculates |op1| * op2, op2 is always positive (larger than zero). + * Dest needs to be distinct from op1. + */ +void __mpa_abs_mul_word(mpanum dest, const mpanum op1, mpa_word_t op2) +{ + mpa_word_t i; + mpa_word_t carry; + mpa_word_t *prod; + const mpa_word_t *a; + + /* clear dest digits */ + mpa_memset(dest->d, 0, dest->alloc * BYTES_PER_WORD); + + a = op1->d; + prod = dest->d; + carry = 0; + for (i = 0; i < __mpanum_size(op1); i++) { + __mpa_mul_add_word(*a, op2, prod + i, &carry); + a++; + } + dest->size = i; + if (carry) { + *(prod + i) = carry; + dest->size++; + } +} + +/* -------------------------------------------------------------------- + * Function: __mpa_abs_mul + * + * Calculates |op1| * |op2| and puts result in dest. + * dest must be big enough to hold result and cannot be + * the same as op1 or op2. + */ +void __mpa_abs_mul(mpanum dest, const mpanum op1, const mpanum op2) +{ + mpa_word_t i = 0; + mpa_word_t j = 0; + mpa_word_t carry = 0; + mpa_word_t *prod; + const mpa_word_t *a; + const mpa_word_t *b; + + /* clear dest digits */ + mpa_memset(dest->d, 0, dest->alloc * BYTES_PER_WORD); + + a = op1->d; + prod = dest->d; + for (i = 0; i < __mpanum_size(op1); i++) { + b = op2->d; + carry = 0; + for (j = 0; j < __mpanum_size(op2); j++) { + __mpa_mul_add_word_cum(*a, *b, prod + j, &carry); + b++; + } + if (carry) + *(prod + j) = carry; + a++; + prod++; + } + dest->size = i + j - 1; + if (carry) + dest->size++; +} + +/************************************************************* + * + * LIB FUNCTIONS + * + *************************************************************/ + +/* -------------------------------------------------------------------- + * Function: mpa_mul + * + * dest = op1 * op2 + */ +void mpa_mul(mpanum dest, + const mpanum op1, const mpanum op2, mpa_scratch_mem pool) +{ + mpanum tmp_dest; + char mem_marker; + + MEMPOOL_MARKER(pool); + + if (__mpanum_is_zero(op1) || __mpanum_is_zero(op2)) { + mpa_set_word(dest, 0); + return; + } + + /* handle the case when dest is one of the operands */ + mem_marker = (dest == op1 || dest == op2); + if (mem_marker) + mpa_alloc_static_temp_var(&tmp_dest, pool); + else + tmp_dest = dest; + + __mpa_abs_mul(tmp_dest, op1, op2); + + if (__mpanum_sign(op1) != __mpanum_sign(op2)) + __mpanum_neg(tmp_dest); + + mpa_copy(dest, tmp_dest); + if (mem_marker) + mpa_free_static_temp_var(&tmp_dest, pool); + MEMPOOL_SANITY_CHECK(pool); +} + +/* -------------------------------------------------------------------- + * Function: mpa_mul_word + * + * Calculates op1 * op2, where op2 is a word, puts result in dest. + */ +void mpa_mul_word(mpanum dest, + const mpanum op1, mpa_word_t op2, mpa_scratch_mem pool) +{ + int sign_1; + mpanum tmp_dest; + char mem_marker; + + if (__mpanum_is_zero(op1) || op2 == 0) { + mpa_set_word(dest, 0); + return; + } + + sign_1 = __mpanum_sign(op1); + + /* handle the case when dest is the operand */ + mem_marker = (dest == op1); + if (mem_marker) + mpa_alloc_static_temp_var(&tmp_dest, pool); + else + tmp_dest = dest; + + __mpa_abs_mul_word(tmp_dest, op1, op2); + + if (sign_1 == MPA_NEG_SIGN) + __mpanum_neg(tmp_dest); + mpa_copy(dest, tmp_dest); + if (mem_marker) + mpa_free_static_temp_var(&tmp_dest, pool); +} diff --git a/lib/libmpa/mpa_primetable.h b/lib/libmpa/mpa_primetable.h new file mode 100644 index 00000000000..38c06167ef2 --- /dev/null +++ b/lib/libmpa/mpa_primetable.h @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef GUARD_PRIMETABLE_H +#define GUARD_PRIMETABLE_H + +#include + +/* Primes Number Table + * All numbers up to 49999 are represented + * by a bit in the following array. + * A 0 means composite and a 1 mean a prime. + * For an odd number 3<= n <= 49999 we can find out + * if n is a prime by doing: + * n = (n-3)>>1; + * IsPrime = (PRIME_TABLE[n>>5] >> (n & 0x1f)) & 0x1) == 1; + * E.i., the primality of each odd number is stored as a bit. + */ +const uint32_t MAX_TABULATED_PRIME = 49999; +const uint32_t NR_STORED_PRIMES = 5133; +const uint32_t PRIME_TABLE[782] = { + 0x325a65b7, 0x40b6894d, 0xc3252619, 0x90cb4106, 0x2d021a64, 0x5244b090, + 0x94c308a2, 0x25144168, + 0x99212018, 0x841a4c90, 0x21128325, 0x8a452442, 0x36182102, 0x05a05a04, + 0x09288450, 0x32824494, + 0x4026184c, 0xc009224b, 0xa0892110, 0x60108264, 0x004c1699, 0x84022480, + 0x41344b40, 0x110412d8, + 0xa05144a4, 0x4802132c, 0x1821a003, 0x34804922, 0x04044108, 0x092086d2, + 0x12006030, 0x04309169, + 0xc10d8242, 0x00886980, 0x60225001, 0x0a48b011, 0x02532006, 0x04904a69, + 0x0029104a, 0x26510804, + 0x2880c100, 0xd2458408, 0xa2184d12, 0x01a60840, 0x40291281, 0x10422484, + 0x0c001928, 0x1208a051, + 0x80c20094, 0x0520d000, 0x1b002289, 0x94930004, 0x6030c141, 0x88080240, + 0x24110036, 0x6106132c, + 0x1244a408, 0x22902c10, 0x0c801244, 0x08601281, 0x008a0434, 0x40141965, + 0x13258200, 0x30480980, + 0x6812c041, 0x19080080, 0x90c32186, 0x21840008, 0x08240212, 0x80494806, + 0x00169021, 0x12440483, + 0x84996020, 0x29804104, 0xcb400440, 0x200040a0, 0x04240824, 0x902c244b, + 0x10406194, 0x49304a01, + 0x11409000, 0x02d00822, 0x2480c820, 0x00050210, 0xa41a4492, 0x60164009, + 0x920014c1, 0x04000422, + 0x29021b4c, 0x02680242, 0x22484500, 0x0c329941, 0x81050048, 0x14012000, + 0x49025220, 0x43088218, + 0x16002104, 0x64840229, 0x89243042, 0x22124c84, 0x01801200, 0x8800108a, + 0x02990d00, 0x20201044, + 0x42618483, 0x301800a0, 0x08b4010c, 0x51010648, 0x94c30002, 0x41120a44, + 0x40042081, 0x04400c82, + 0x21340908, 0x81000252, 0x06030830, 0x09008008, 0xca019008, 0x32892110, + 0x05064a0c, 0x8a009402, + 0x20520514, 0x00a00068, 0x90208248, 0xa4412016, 0x08001060, 0x12040098, + 0x12422c82, 0x41148100, + 0x012c3080, 0x240b40a4, 0x08908008, 0x50650003, 0x82000120, 0x21005848, + 0x83408602, 0x128a2404, + 0x08929049, 0x43050050, 0x24016086, 0x04229000, 0x034c0019, 0x00110982, + 0x40a40241, 0x0941220a, + 0xa0080c12, 0x68144021, 0x12409002, 0x96006c32, 0x20840904, 0x81000051, + 0x20906520, 0x0c008860, + 0x520c0252, 0x904a0910, 0x01205041, 0x02402219, 0x06000c00, 0x45304320, + 0x89443200, 0x00410082, + 0x6080d125, 0x8204b088, 0xb0004400, 0x04205a00, 0x40018083, 0x024a2004, + 0x40149045, 0x81290601, + 0x00422100, 0x01324240, 0x18002419, 0x10912022, 0x61840100, 0x10680250, + 0x200b0c20, 0x29140020, + 0x8a410448, 0x84080c00, 0x05204104, 0x40499050, 0x10006004, 0x00828029, + 0x0308a008, 0x80004106, + 0x4d224825, 0x48401400, 0x84832502, 0x00140121, 0x800c009a, 0xa24004b2, + 0x01120001, 0x8a2430c1, + 0x14090020, 0x28841a00, 0x48090282, 0x30424494, 0x08248809, 0x4124a013, + 0x00884880, 0x44201205, + 0x02082608, 0x16512800, 0x05244820, 0x092800d8, 0x82520004, 0x49145004, + 0x88218001, 0xa0900110, + 0x04001940, 0x80290602, 0x10422490, 0x40808108, 0x91202408, 0xb4c20080, + 0x64009860, 0x00442201, + 0x16810086, 0x00308960, 0x18600050, 0x840900a0, 0x40001005, 0x4200a04a, + 0x00190020, 0x05804208, + 0x83008012, 0x20c24514, 0x04040840, 0xc001a64a, 0xa04b2000, 0x28101020, + 0x51449291, 0x10522020, + 0x00944301, 0x08251090, 0x040a0004, 0x21128220, 0x08219081, 0x90804902, + 0x0c265008, 0xc2018491, + 0x020844a0, 0x00921141, 0x4204040a, 0x04806084, 0x4520d821, 0x1b400001, + 0x92502482, 0x01000048, + 0x814920ca, 0x84030400, 0x68008004, 0x4044940b, 0xb4000030, 0x28064800, + 0x40200090, 0x20982120, + 0x40929000, 0x0024a003, 0x24890084, 0x0c105000, 0x53008298, 0x14120800, + 0x64100100, 0x09440010, + 0x00494806, 0x21009301, 0x0200248b, 0x00812112, 0x0d064044, 0x00080440, + 0x224a0130, 0x08b48044, + 0x50090418, 0x00420992, 0x60328041, 0x18001408, 0x80900182, 0x64008308, + 0x10610040, 0x86410804, + 0x29060109, 0xd8002003, 0x00882030, 0x0802434c, 0x0a490442, 0x20c020b0, + 0x4082080d, 0x9020a011, + 0x20802914, 0x08301a04, 0x08009400, 0x04420020, 0x24104821, 0x01290202, + 0x02100400, 0x0006c100, + 0x88012041, 0xa0102402, 0x0080004c, 0x00601203, 0x10824134, 0x04220809, + 0x53200002, 0x848b6810, + 0x01209264, 0x49048610, 0x00000920, 0x21848020, 0x814c1042, 0x80120880, + 0x01801221, 0x18208448, + 0x26102c12, 0x08044140, 0x83409292, 0x100804a0, 0x4022080c, 0x92250008, + 0x144a0086, 0x60001840, + 0x42083001, 0x04800106, 0x0400c101, 0x10610208, 0x020304b4, 0x0880000c, + 0x88058448, 0x06014110, + 0x00045b08, 0x81208013, 0x10922500, 0x4012100d, 0x80012200, 0x80012016, + 0x08104a45, 0x53481000, + 0x960009a0, 0x00b0c308, 0x010820c0, 0x24184082, 0x28141024, 0x084510c0, + 0x04880402, 0x21240808, + 0x49410650, 0x02906030, 0x00a01069, 0xc1040200, 0x00014116, 0x2420c024, + 0x02488008, 0x00420182, + 0x00340261, 0x11603200, 0xa2190420, 0x48804304, 0x00009401, 0x12002432, + 0x21804808, 0xc3291080, + 0x104845a0, 0x44041020, 0x1009a202, 0xb0420100, 0x20124840, 0x08040018, + 0x00810404, 0x21900208, + 0x0948205a, 0x264000b4, 0x6004000c, 0x08202489, 0xa0800d12, 0x08261244, + 0x88290200, 0x20902504, + 0x08b49124, 0x0308040a, 0x14424012, 0x20000800, 0x13040088, 0x14032404, + 0x21008a00, 0x10050242, + 0x04410080, 0x09124100, 0x50202002, 0x02084820, 0x08201148, 0x08401610, + 0x02002194, 0x4080802c, + 0x9004a408, 0x00024190, 0x00225221, 0x50083600, 0x80402422, 0x64a44041, + 0x81000000, 0x82580802, + 0x08148209, 0x02042049, 0x80114122, 0x0c80100c, 0x48408090, 0x20804530, + 0x08228160, 0xd1010002, + 0x90882004, 0x21009024, 0x0a001618, 0x021100a2, 0x44844901, 0x88401082, + 0xa0100082, 0x00024020, + 0x58200489, 0x00992c32, 0x20804804, 0xc0608482, 0x00480430, 0x0092004d, + 0x93010409, 0x04034102, + 0x24100004, 0x120c0010, 0x800101a4, 0x00048008, 0x882500c2, 0x02004c00, + 0x6000430c, 0x40409000, + 0x02980802, 0x25065a00, 0x014894c1, 0x22100014, 0x48960060, 0x5100a040, + 0x84820900, 0x04001061, + 0x11080601, 0x96000002, 0x60004308, 0x19090000, 0x204044a0, 0x28028120, + 0x52413043, 0x26890530, + 0x09044840, 0x0a0104c0, 0x101200a4, 0x48220045, 0x01008202, 0x00096880, + 0x00200205, 0x12409099, + 0x10420c84, 0x44840201, 0x01011240, 0x22410c34, 0x20108021, 0xc0009400, + 0xa0104122, 0x01064008, + 0xc8201200, 0x10102000, 0x0c941028, 0x1004a000, 0x30024004, 0x04104020, + 0x1a04a498, 0x12120880, + 0x61208041, 0x01490200, 0x06004012, 0x00805001, 0x8220b003, 0x80806810, + 0x09240000, 0x09488242, + 0x22120004, 0x0c208900, 0x40208613, 0x90022900, 0x48120004, 0x010c2410, + 0x04d10180, 0x45000a68, + 0x002512c2, 0x200a4c10, 0x0002d100, 0x8a200000, 0x16102c00, 0x04804240, + 0x01489010, 0x20d80104, + 0x04801804, 0x810c0008, 0x00010110, 0x04221200, 0x59003009, 0x06010922, + 0x64204060, 0x90280210, + 0x82580002, 0x29948205, 0x18243080, 0x14904100, 0x29800b00, 0x08219011, + 0x02400024, 0x00200069, + 0xc001a251, 0x04020014, 0x20320260, 0x42049418, 0x10c02822, 0x60004901, + 0x11443008, 0x00004004, + 0x4182420c, 0x9040804b, 0x22800102, 0x28804244, 0xc3289010, 0x004a25a0, + 0x08840040, 0x402c2610, + 0x90030182, 0x04028044, 0x00480291, 0x04c10020, 0x00000028, 0x106120d0, + 0x040b0004, 0x68109320, + 0xc8408448, 0x22010020, 0x05060804, 0x024804c3, 0x02506400, 0x44901804, + 0x11088042, 0x04002016, + 0x2400d801, 0x10048081, 0x00020182, 0x21300140, 0x08251098, 0x800104a2, + 0x09001200, 0x524010c1, + 0x82010810, 0x0c205048, 0x83010002, 0x028004b4, 0x0000812c, 0x00002400, + 0x10490180, 0x64009a00, + 0x18042410, 0x90402104, 0x00b44848, 0x81092002, 0x84090030, 0x08805000, + 0x02241082, 0x86004912, + 0x00024200, 0x4b090080, 0x20d000a0, 0x44141144, 0x40212200, 0x008a0912, + 0x0d304821, 0x08408208, + 0x94830424, 0x01200141, 0x88403212, 0x20084002, 0x21040101, 0x100480c2, + 0xb0002802, 0x09a01808, + 0x80408201, 0x22900404, 0x48308825, 0x81040613, 0x30004890, 0x01000201, + 0x03040600, 0x84422404, + 0x40000108, 0x102d0052, 0x02024400, 0x00048001, 0x0a24840a, 0x82006410, + 0x2ca05048, 0x08090040, + 0x32c04000, 0x00020000, 0x800ca040, 0x30420190, 0x0d120260, 0x40403089, + 0x04820104, 0x04100921, + 0x9048021a, 0x80500080, 0x48840005, 0x1a012049, 0xb0884420, 0x2000010c, + 0x40601282, 0x10820434, + 0x00021140, 0x42008650, 0x04002090, 0x45100045, 0x02442400, 0x04410882, + 0x2484c320, 0x88002052, + 0x02510080, 0x40064028, 0xd0412400, 0xa0890c00, 0x20a40200, 0x00009200, + 0x000a4400, 0x00b40001, + 0x11250410, 0x80404184, 0x61008244, 0x1a000000, 0x14410002, 0x25208101, + 0x814102c8, 0x82124004, + 0x49008020, 0x0a009440, 0x26102800, 0x21825808, 0x824810d2, 0x22000100, + 0x04320024, 0x10210003, + 0x00c90104, 0x28100025, 0x11481299, 0x84000482, 0x0090c008, 0x19000288, + 0x044a4404, 0x60869204, + 0x1005a040, 0x02090c20, 0x08201100, 0x41608293, 0x12180080, 0x04209101, + 0x800d2412, 0x14096912, + 0x20020021, 0x01002098, 0x92100980, 0x44844268, 0x00290240, 0x00520c22, + 0x48900300, 0x10210488, + 0x14182012, 0x20204200, 0x82080440, 0x20020404, 0x0c801104, 0x40000001, + 0x90810116, 0x20104800, + 0x1a000600, 0x80902c24, 0x40100221, 0x8048000a, 0x000008b6, 0x01801020, + 0x98442008, 0x32802502, + 0x0c041208, 0x40019442, 0x20582110, 0x0cb48800, 0x40000002, 0x80026102, + 0x00028000, 0x4b041291, + 0x00110102, 0x00948868, 0x08043050, 0x220b0082, 0x01140108, 0x42202441, + 0x14114810, 0x20000240, + 0xc0001202, 0x30080194, 0x40800024, 0x10288050, 0x80806886, 0x49021020, + 0x49080000, 0x82822100, + 0x40204300, 0x90291008, 0x24080010, 0x68000105, 0x40242089, 0xa4000002, + 0x00021104, 0x08218012, + 0x22000530, 0x04161009, 0xc2002210, 0x84032004, 0x40200060, 0x094c0010, + 0x10510824, 0x60244200, + 0x09481008, 0x00414c04, 0x01825005, 0x00619400, 0x02082122, 0x00200204, + 0x80080280, 0x02400190, + 0x08348944, 0x02040200, 0xa4420102, 0x0c100224, 0x18403201, 0x00010084, + 0x04248929, 0x08442090, + 0x801a0424, 0x6802c300, 0xc2418000, 0x20812010, 0x20244008, 0x00289051, + 0x00802480, 0x0c201048, + 0x91012001, 0x04402002, 0x0c100841, 0x41008280, 0x82002c20, 0x0094c840, + 0x11003250, 0x005100a0, + 0x0006820c, 0x4a403000, 0x06884130, 0x09061840, 0x09000010, 0x10906020, + 0x0820812c, 0x0101a240, + 0x14c80982, 0x60220004, 0x13001080, 0x80c00d00, 0x05100a09, 0x9900100a, + 0x20000430, 0x40049021, + 0x40408083, 0x34002130, 0x21044148, 0xc0010240, 0x00020584, 0x0000004c +}; + +#endif /* include guard */ diff --git a/lib/libmpa/mpa_primetest.c b/lib/libmpa/mpa_primetest.c new file mode 100644 index 00000000000..9ada05bd342 --- /dev/null +++ b/lib/libmpa/mpa_primetest.c @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "mpa.h" + +/* + * Remove the #undef if you like debug print outs and assertions + * for this file. + */ +/*#undef DEBUG_ME */ +#include "mpa_debug.h" +#include "mpa_assert.h" + +#define USE_PRIME_TABLE + +#if defined(USE_PRIME_TABLE) +#include "mpa_primetable.h" +#endif + +#define DEF_COMPOSITE 0 +#define DEF_PRIME 1 +#define PROB_PRIME -1 + +/* Product of all primes < 1000 */ +static const mpa_num_base const_small_prime_factors = { + 44, + 44, + {0x2ED42696, 0x2BBFA177, 0x4820594F, 0xF73F4841, + 0xBFAC313A, 0xCAC3EB81, 0xF6F26BF8, 0x7FAB5061, + 0x59746FB7, 0xF71377F6, 0x3B19855B, 0xCBD03132, + 0xBB92EF1B, 0x3AC3152C, 0xE87C8273, 0xC0AE0E69, + 0x74A9E295, 0x448CCE86, 0x63CA1907, 0x8A0BF944, + 0xF8CC3BE0, 0xC26F0AF5, 0xC501C02F, 0x6579441A, + 0xD1099CDA, 0x6BC76A00, 0xC81A3228, 0xBFB1AB25, + 0x70FA3841, 0x51B3D076, 0xCC2359ED, 0xD9EE0769, + 0x75E47AF0, 0xD45FF31E, 0x52CCE4F6, 0x04DBC891, + 0x96658ED2, 0x1753EFE5, 0x3AE4A5A6, 0x8FD4A97F, + 0x8B15E7EB, 0x0243C3E1, 0xE0F0C31D, 0x0000000B} +}; + +/* + * If n is less than this number (341550071728321 decimal) the Miller-Rabin + * test (using specific bases) constitutes a primality proof. + */ +static const mpa_num_base const_miller_rabin_proof_limit = { + 2, + 2, + {0x52B2C8C1, 0x000136A3} +}; + +static const mpa_num_base const_two = { + 1, + 1, + {0x00000002} +}; + +/* foward declarations */ +static int is_small_prime(mpanum n); +static int has_small_factors(mpanum n, mpa_scratch_mem pool); +static int primality_test_miller_rabin(mpanum n, int conf_level, + mpa_scratch_mem pool); + +/*------------------------------------------------------------ + * + * mpa_is_prob_prime + * + * Returns: + * 0 if n is definitely composite + * 1 if n is definitely prime + * -1 if n is composite with a probability less than 2^(-conf_level) + * + */ +int mpa_is_prob_prime(mpanum n, int conf_level, mpa_scratch_mem pool) +{ + int result = 0; + + MEMPOOL_MARKER(pool); + + /* Check if it's a small prime */ + result = is_small_prime(n); + if (result != PROB_PRIME) { + DPRINT("IsProbPrime: is_small_prime decided = %d\n", result); + goto cleanup; + } + /* Test if n is divisible by any prime < 1000 */ + if (has_small_factors(n, pool)) { + DPRINT("IsProbPrime: has_small_factors decided = 0.\n"); + result = DEF_COMPOSITE; + goto cleanup; + } + /* Check with Miller Rabin */ + result = primality_test_miller_rabin(n, conf_level, pool); + DPRINT("IsPrime: MR decided = %d.\n", result); + +cleanup: + MEMPOOL_SANITY_CHECK(pool); + return result; +} + +#if defined(USE_PRIME_TABLE) +/*------------------------------------------------------------ + * + * check_table + * + */ +static uint32_t check_table(uint32_t v) +{ + return (PRIME_TABLE[v >> 5] >> (v & 0x1f)) & 1; +} +#endif + +/*------------------------------------------------------------ + * + * is_small_prime + * + * Returns 1 if n is prime, + Returns 0 if n is composite + * Returns -1 if we cannot decide + * + */ +static int is_small_prime(mpanum n) +{ + mpa_word_t v; + + /* If n is larger than a mpa_word_t, we can only decide if */ + /* n is even. If it's odd we cannot tell. */ + if (__mpanum_size(n) > 1) + return ((mpa_parity(n) == MPA_EVEN_PARITY) ? 0 : -1); + + v = mpa_get_word(n); /* will convert negative n:s to positive v:s. */ + if ((v | 1) == 1) /* 0 and 1 are not prime */ + return DEF_COMPOSITE; + if (v == 2) /* 2 is prime */ + return DEF_PRIME; + if ((v & 1) == 0) + return DEF_COMPOSITE; /* but no other even number */ + +#if defined(USE_PRIME_TABLE) + if (mpa_cmp_short(n, MAX_TABULATED_PRIME) > 0) + return -1; + v = (v - 3) >> 1; + return check_table(v); +#else + return -1; +#endif +} + +/*------------------------------------------------------------ + * + * has_small_factors + * + * returns 1 if n has small factors + * returns 0 if not. + */ +static int has_small_factors(mpanum n, mpa_scratch_mem pool) +{ + const mpa_num_base *factors = &const_small_prime_factors; + int result; + mpanum res; + + MEMPOOL_MARKER(pool); + + mpa_alloc_static_temp_var(&res, pool); + mpa_gcd(res, n, (const mpanum)factors, pool); + result = (mpa_cmp_short(res, 1) == 0) ? 0 : 1; + mpa_free_static_temp_var(&res, pool); + + MEMPOOL_SANITY_CHECK(pool); + return result; +} + +/*------------------------------------------------------------ + * + * primality_test_miller_rabin + * + */ +static int primality_test_miller_rabin(mpanum n, int conf_level, + mpa_scratch_mem pool) +{ + int result; + bool proof_version; + static const int32_t proof_a[7] = { 2, 3, 5, 7, 11, 13, 17 }; + int cnt; + int idx; + int t; + int e = 0; + int cmp_one; + mpanum a; + mpanum q; + mpanum n_minus_1; + mpanum b; + mpanum r_modn; + mpanum r2_modn; + mpa_word_t n_inv; + + /* DPRINT("Checking primality\n"); */ + /* DPRINT_MPANUM_HEXSTR("n is", n, "\n"); */ + + MEMPOOL_MARKER(pool); + + mpa_alloc_static_temp_var(&r_modn, pool); + mpa_alloc_static_temp_var(&r2_modn, pool); + + if (mpa_compute_fmm_context(n, r_modn, r2_modn, &n_inv, pool) == -1) { + DPRINT("Couldn't compute n_inv so n is not prime\n"); + result = DEF_COMPOSITE; + goto cleanup_short; + } + /* DPRINT_MPANUM_HEXSTR("r_modn is ", r_modn, "\n"); */ + /* DPRINT_MPANUM_HEXSTR("r2_modn is ", r2_modn, "\n"); */ + + mpa_alloc_static_temp_var(&a, pool); + mpa_alloc_static_temp_var(&q, pool); + mpa_alloc_static_temp_var(&n_minus_1, pool); + mpa_alloc_static_temp_var(&b, pool); + + proof_version = + (mpa_cmp(n, (mpanum) &const_miller_rabin_proof_limit) < 0); + + if (proof_version) { + DPRINT("Using proof version of Miller-Rabin\n"); + cnt = 7; + } else { + /* MR has 1/4 chance in failing a composite */ + cnt = (conf_level + 1) / 2; + } + + mpa_sub_word(n_minus_1, n, 1, pool); + mpa_set(q, n_minus_1); + t = 0; + /* calculate q such that n - 1 = 2^t * q where q is odd */ + while (mpa_is_even(q)) { + mpa_shift_right(q, q, 1); + t++; + } + + /* DPRINT_MPANUM_HEXSTR("q is ", q, "\n"); */ + + result = PROB_PRIME; + for (idx = 0; idx < cnt && result == PROB_PRIME; idx++) { + if (proof_version) { + mpa_set_S32(a, proof_a[idx]); + if (mpa_cmp(n, a) == 0) { + result = DEF_PRIME; + continue; + } + } else { + /* + * Get random a, 1 < a < N by + * asking for a random in range 0 <= x < N - 2 + * and then add 2 to it. + */ + mpa_sub_word(n_minus_1, n_minus_1, 1, pool); + /* n_minus_1 is now N - 2 ! */ + mpa_get_random(a, n_minus_1); + mpa_add_word(n_minus_1, n_minus_1, 1, pool); + /* and a is now 2 <= a < N */ + mpa_add_word(a, a, 2, pool); + + /* DPRINT_MPANUM_HEXSTR("a is", a, "\n"); */ + } + + mpa_exp_mod(b, a, q, n, r_modn, r2_modn, n_inv, pool); + /* DPRINT_MPANUM_HEXSTR("first b is", b, "\n"); */ + e = 0; + +inner_loop: + cmp_one = mpa_cmp_short(b, 1); + if ((cmp_one == 0) && (e > 0)) { + result = DEF_COMPOSITE; + continue; + } + + if ((mpa_cmp(b, n_minus_1) == 0) || + ((cmp_one == 0) && (e == 0))) { + /* probably prime, try another a */ + continue; + } + + e++; + if (e < t) { + mpa_exp_mod(b, b, (mpanum) &const_two, n, r_modn, + r2_modn, n_inv, pool); + /* DPRINT_MPANUM_HEXSTR("later b is", b, "\n"); */ + goto inner_loop; + } + result = DEF_COMPOSITE; + } + + if (result == PROB_PRIME && proof_version) + result = DEF_PRIME; + + mpa_free_static_temp_var(&a, pool); + mpa_free_static_temp_var(&q, pool); + mpa_free_static_temp_var(&n_minus_1, pool); + mpa_free_static_temp_var(&b, pool); +cleanup_short: + mpa_free_static_temp_var(&r_modn, pool); + mpa_free_static_temp_var(&r2_modn, pool); + + MEMPOOL_SANITY_CHECK(pool); + return result; +} diff --git a/lib/libmpa/mpa_random.c b/lib/libmpa/mpa_random.c new file mode 100644 index 00000000000..fc610a8d1d7 --- /dev/null +++ b/lib/libmpa/mpa_random.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "mpa.h" + +/* + * Remove the #undef if you like debug print outs and assertions + * for this file. + */ +/*#undef DEBUG_ME */ +#include "mpa_debug.h" +#include "mpa_assert.h" +#include + +/* This function ends to the real RNG of the platform + * Depending where the libmpa is used: + * - kernel side: the implementation is found in the TEECore + * - user side: the implementation is found in libutee + */ +TEE_Result get_rng_array(void *buf, size_t blen); + +static uint8_t get_random_byte(void) +{ + uint8_t buf; + while (get_rng_array(&buf, 1) != TEE_SUCCESS) + ; + + return buf; +} + +/*------------------------------------------------------------ + * + * mpa_get_random + * + */ +void mpa_get_random(mpanum dest, mpanum limit) +{ + int done = 0; + + mpa_wipe(dest); + if (__mpanum_alloced(dest) < __mpanum_size(limit)) + dest->size = __mpanum_alloced(dest); + else + dest->size = __mpanum_size(limit); + while (!done) { + for (int idx = 0; idx < dest->size; idx++) { + mpa_word_t w = 0; + for (int j = 0; j < BYTES_PER_WORD; j++) + w = (w << 8) ^ get_random_byte(); + dest->d[idx] = w; + } + if (dest->size < __mpanum_size(limit)) { + done = 1; + } else { + mpa_word_t hbi = + (mpa_word_t) mpa_highest_bit_index(limit); + /* 1 <= hbi <= WORD_SIZE */ + hbi = (hbi % WORD_SIZE) + 1; + if (hbi < WORD_SIZE) { + hbi = (1 << hbi) - 1; + dest->d[dest->size - 1] &= hbi; + } + done = (mpa_cmp(dest, limit) < 0) ? 1 : 0; + } + } +} diff --git a/lib/libmpa/mpa_shift.c b/lib/libmpa/mpa_shift.c new file mode 100644 index 00000000000..03a81cdd747 --- /dev/null +++ b/lib/libmpa/mpa_shift.c @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "mpa.h" + +/* + * Remove the #undef if you like debug print outs and assertions + * for this file. + */ +/*#undef DEBUG_ME */ +#include "mpa_debug.h" +#include "mpa_assert.h" + +/************************************************************* + * + * HELPER FUNCTIONS + * + *************************************************************/ + +/*------------------------------------------------------------ + * + * __mpa_shift_words_left + * + */ +void __mpa_shift_words_left(mpanum op, mpa_word_t q) +{ + mpa_word_t i; + + if (q == 0 || __mpanum_is_zero(op)) + return; + for (i = __mpanum_size(op) + q - 1; i > q - 1; i--) + op->d[i] = op->d[i - q]; + + mpa_memset(op->d, 0, BYTES_PER_WORD * q); + + /* update the size of op */ + if (op->size > 0) + op->size += q; + else + op->size -= q; +} + +/*------------------------------------------------------------ + * + * __mpa_shift_words_right + * + */ +void __mpa_shift_words_right(mpanum op, mpa_word_t q) +{ + mpa_word_t i; + + if (q == 0 || __mpanum_is_zero(op)) + return; + + if (q >= __mpanum_size(op)) { + mpa_set_word(op, 0); + return; + } + + for (i = 0; i < __mpanum_size(op) - q; i++) + op->d[i] = op->d[i + q]; + + /* update the size of dest */ + if (op->size > 0) + op->size -= q; + else + op->size += q; +} + +/************************************************************* + * + * LIB FUNCTIONS + * + *************************************************************/ + +/* -------------------------------------------------------------------- + * mpa_shift_left + * + * Shifts src left by "steps" step and put result in dest. + * It does not care about signs. Dest will have same sign as src. + */ +void mpa_shift_left(mpanum dest, mpanum src, mpa_word_t steps) +{ + mpa_word_t q; /* quotient of steps div WORD_SIZE */ + mpa_word_t r; /* remainder of steps div WORD_SIZE */ + mpa_word_t i; + /* the bits of the word which will be shifted into another word */ + mpa_word_t rbits; + mpa_word_t need_extra_word; + + /* + * Copy first, then check, since even a shifted zero should + * be copied. + */ + mpa_copy(dest, src); + __mpa_set_unused_digits_to_zero(dest); + if (steps == 0 || __mpanum_is_zero(dest)) + return; + + r = steps & (WORD_SIZE - 1); /* 0 <= r < WORD_SIZE */ + q = steps >> LOG_OF_WORD_SIZE; /* 0 <= q */ + + /* + * The size of dest will always increase by at least q. + * If we're shifting r bits and the r highest bits in + * the MSW of dest is zero, we don't need the extra word + * Note: + * We cannot do + * if (_mpanumMSW(dest) >> (WORD_SIZE - r)) + * since some compilers (MS) does not shift the word + * if the shift quantity is larger or equal to the word size... + * Otherwise it would be natural to say that (a >> b) is just zero + * if b is larger than the number of bit of a, but no no... + */ + need_extra_word = 0; + if (__mpanum_msw(dest) & (((1 << r) - 1) << (WORD_SIZE - r))) + need_extra_word = 1; + + if (r == 0) { /* and q > 0 */ + /* + * We have a simple shift by words + */ + for (i = __mpanum_size(dest) + q - 1; i > q - 1; i--) + dest->d[i] = dest->d[i - q]; + } else { + /* + * We have a combination of word and bit shifting. + * + * If need_extra_word is 1, the MSW is special and handled + * here + */ + i = __mpanum_size(dest) + q + need_extra_word; + if (need_extra_word) { + rbits = dest->d[i - q - 1] >> (WORD_SIZE - r); + dest->d[i] ^= rbits; + } + i--; + dest->d[i] = dest->d[i - q] << r; + while (i > q) { + rbits = dest->d[i - q - 1] >> (WORD_SIZE - r); + dest->d[i] ^= rbits; + i--; + dest->d[i] = dest->d[i - q] << r; + } + } + mpa_memset(dest->d, 0, BYTES_PER_WORD * q); + /* update the size of dest */ + if (dest->size > 0) + dest->size += q + need_extra_word; + else + dest->size -= q + need_extra_word; +} + +/*------------------------------------------------------------ + * + * mpa_shift_right + * + * Shifts src right by "steps" step and put result in dest. + * It does not care about signs. Dest will have same sign as src. + * + */ +void mpa_shift_right(mpanum dest, mpanum src, mpa_word_t steps) +{ + mpa_word_t q; /* quotient of steps div WORD_SIZE */ + mpa_word_t r; /* remainder of steps div WORD_SIZE */ + mpa_word_t i; + /* the bits of the word which will be shifted into another word */ + mpa_word_t rbits; + + /* + * Copy first, then check, since even a shifted zero should + * be copied. + */ + mpa_copy(dest, src); + __mpa_set_unused_digits_to_zero(dest); + if (steps == 0 || __mpanum_is_zero(dest)) + return; + + r = steps & (WORD_SIZE - 1); /* 0 <= r < WORD_SIZE */ + q = steps >> LOG_OF_WORD_SIZE; /* 0 <= q */ + + if (q >= __mpanum_size(dest)) { + mpa_set_word(dest, 0); + return; + } + + /* + * Here we have: + * 0 <= r < WORD_SIZE - 1 + * 0 <= q < _mpanumSize(dest) + */ + if (r == 0) { /* and q > 0 */ + /* Simple shift by words */ + for (i = 0; i < __mpanum_size(dest) - q; i++) + dest->d[i] = dest->d[i + q]; + } else { + /* combination of word and bit shifting */ + for (i = 0; i < __mpanum_size(dest) - q - 1; i++) { + dest->d[i] = dest->d[i + q]; + rbits = dest->d[i + q + 1] & ((1 << r) - 1); + dest->d[i] = + (dest->d[i] >> r) ^ (rbits << (WORD_SIZE - r)); + } + /* final word is special */ + dest->d[i] = dest->d[i + q] >> r; + } + + /* update the size of dest */ + if (dest->size > 0) + dest->size -= q; + else + dest->size += q; + + /* Take care of the case when we shifted out all bits from MSW */ + if (__mpanum_msw(dest) == 0) { + if (dest->size > 0) + dest->size--; + else + dest->size++; + } +} diff --git a/lib/libmpa/sub.mk b/lib/libmpa/sub.mk new file mode 100644 index 00000000000..deaeb7a0a29 --- /dev/null +++ b/lib/libmpa/sub.mk @@ -0,0 +1,42 @@ +global-incdirs-y += include + +srcs-y += mpa_misc.c +cflags-remove-mpa_misc.c-y += -pedantic +cflags-mpa_misc.c-y += -Wno-sign-compare + +srcs-y += mpa_montgomery.c +cflags-remove-mpa_montgomery.c-y += -Wdeclaration-after-statement + +srcs-y += mpa_primetest.c +cflags-remove-mpa_primetest.c-y += -pedantic + +srcs-y += mpa_conv.c +cflags-mpa_conv.c-y += -Wno-sign-compare + +srcs-y += mpa_div.c +cflags-mpa_div.c-y += -Wno-sign-compare + +srcs-y += mpa_gcd.c +cflags-mpa_gcd.c-y += -Wno-sign-compare + +srcs-y += mpa_mem_static.c +cflags-mpa_mem_static.c-y += -Wno-sign-compare + +srcs-y += mpa_mul.c +cflags-mpa_mul.c-y += -Wno-sign-compare + +srcs-y += mpa_random.c +cflags-mpa_random.c-y += -Wno-sign-compare + +srcs-y += mpa_shift.c +cflags-mpa_shift.c-y += -Wno-sign-compare + +srcs-y += mpa_addsub.c +srcs-y += mpa_cmp.c +srcs-y += mpa_debug.c +srcs-y += mpa_expmod.c +srcs-y += mpa_init.c +srcs-y += mpa_io.c +srcs-y += mpa_modulus.c + +subdirs-(arch_arm32) += arch/$(ARCH) diff --git a/lib/libutee/abort.c b/lib/libutee/abort.c new file mode 100644 index 00000000000..4217722e864 --- /dev/null +++ b/lib/libutee/abort.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include + +void abort(void) +{ + printf("Abort!\n"); + TEE_Panic(0); +} diff --git a/lib/libutee/arch/arm32/bget.c b/lib/libutee/arch/arm32/bget.c new file mode 100644 index 00000000000..02ec56ec26c --- /dev/null +++ b/lib/libutee/arch/arm32/bget.c @@ -0,0 +1,1628 @@ +/* + + B G E T + + Buffer allocator + + Designed and implemented in April of 1972 by John Walker, based on the + Case Algol OPRO$ algorithm implemented in 1966. + + Reimplemented in 1975 by John Walker for the Interdata 70. + Reimplemented in 1977 by John Walker for the Marinchip 9900. + Reimplemented in 1982 by Duff Kurland for the Intel 8080. + + Portable C version implemented in September of 1990 by an older, wiser + instance of the original implementor. + + Souped up and/or weighed down slightly shortly thereafter by Greg + Lutz. + + AMIX edition, including the new compaction call-back option, prepared + by John Walker in July of 1992. + + Bug in built-in test program fixed, ANSI compiler warnings eradicated, + buffer pool validator implemented, and guaranteed repeatable test + added by John Walker in October of 1995. + + This program is in the public domain. + + 1. This is the book of the generations of Adam. In the day that God + created man, in the likeness of God made he him; + 2. Male and female created he them; and blessed them, and called + their name Adam, in the day when they were created. + 3. And Adam lived an hundred and thirty years, and begat a son in + his own likeness, and after his image; and called his name Seth: + 4. And the days of Adam after he had begotten Seth were eight + hundred years: and he begat sons and daughters: + 5. And all the days that Adam lived were nine hundred and thirty + years: and he died. + 6. And Seth lived an hundred and five years, and begat Enos: + 7. And Seth lived after he begat Enos eight hundred and seven years, + and begat sons and daughters: + 8. And all the days of Seth were nine hundred and twelve years: and + he died. + 9. And Enos lived ninety years, and begat Cainan: + 10. And Enos lived after he begat Cainan eight hundred and fifteen + years, and begat sons and daughters: + 11. And all the days of Enos were nine hundred and five years: and + he died. + 12. And Cainan lived seventy years and begat Mahalaleel: + 13. And Cainan lived after he begat Mahalaleel eight hundred and + forty years, and begat sons and daughters: + 14. And all the days of Cainan were nine hundred and ten years: and + he died. + 15. And Mahalaleel lived sixty and five years, and begat Jared: + 16. And Mahalaleel lived after he begat Jared eight hundred and + thirty years, and begat sons and daughters: + 17. And all the days of Mahalaleel were eight hundred ninety and + five years: and he died. + 18. And Jared lived an hundred sixty and two years, and he begat + Enoch: + 19. And Jared lived after he begat Enoch eight hundred years, and + begat sons and daughters: + 20. And all the days of Jared were nine hundred sixty and two years: + and he died. + 21. And Enoch lived sixty and five years, and begat Methuselah: + 22. And Enoch walked with God after he begat Methuselah three + hundred years, and begat sons and daughters: + 23. And all the days of Enoch were three hundred sixty and five + years: + 24. And Enoch walked with God: and he was not; for God took him. + 25. And Methuselah lived an hundred eighty and seven years, and + begat Lamech. + 26. And Methuselah lived after he begat Lamech seven hundred eighty + and two years, and begat sons and daughters: + 27. And all the days of Methuselah were nine hundred sixty and nine + years: and he died. + 28. And Lamech lived an hundred eighty and two years, and begat a + son: + 29. And he called his name Noah, saying, This same shall comfort us + concerning our work and toil of our hands, because of the ground + which the LORD hath cursed. + 30. And Lamech lived after he begat Noah five hundred ninety and + five years, and begat sons and daughters: + 31. And all the days of Lamech were seven hundred seventy and seven + years: and he died. + 32. And Noah was five hundred years old: and Noah begat Shem, Ham, + and Japheth. + + And buffers begat buffers, and links begat links, and buffer pools + begat links to chains of buffer pools containing buffers, and lo the + buffers and links and pools of buffers and pools of links to chains of + pools of buffers were fruitful and they multiplied and the Operating + System looked down upon them and said that it was Good. + + INTRODUCTION + ============ + + BGET is a comprehensive memory allocation package which is easily + configured to the needs of an application. BGET is efficient in + both the time needed to allocate and release buffers and in the + memory overhead required for buffer pool management. It + automatically consolidates contiguous space to minimise + fragmentation. BGET is configured by compile-time definitions, + Major options include: + + * A built-in test program to exercise BGET and + demonstrate how the various functions are used. + + * Allocation by either the "first fit" or "best fit" + method. + + * Wiping buffers at release time to catch code which + references previously released storage. + + * Built-in routines to dump individual buffers or the + entire buffer pool. + + * Retrieval of allocation and pool size statistics. + + * Quantisation of buffer sizes to a power of two to + satisfy hardware alignment constraints. + + * Automatic pool compaction, growth, and shrinkage by + means of call-backs to user defined functions. + + Applications of BGET can range from storage management in + ROM-based embedded programs to providing the framework upon which + a multitasking system incorporating garbage collection is + constructed. BGET incorporates extensive internal consistency + checking using the mechanism; all these checks can be + turned off by compiling with NDEBUG defined, yielding a version of + BGET with minimal size and maximum speed. + + The basic algorithm underlying BGET has withstood the test of + time; more than 25 years have passed since the first + implementation of this code. And yet, it is substantially more + efficient than the native allocation schemes of many operating + systems: the Macintosh and Microsoft Windows to name two, on which + programs have obtained substantial speed-ups by layering BGET as + an application level memory manager atop the underlying system's. + + BGET has been implemented on the largest mainframes and the lowest + of microprocessors. It has served as the core for multitasking + operating systems, multi-thread applications, embedded software in + data network switching processors, and a host of C programs. And + while it has accreted flexibility and additional options over the + years, it remains fast, memory efficient, portable, and easy to + integrate into your program. + + BGET IMPLEMENTATION ASSUMPTIONS + =============================== + + BGET is written in as portable a dialect of C as possible. The + only fundamental assumption about the underlying hardware + architecture is that memory is allocated is a linear array which + can be addressed as a vector of C "char" objects. On segmented + address space architectures, this generally means that BGET should + be used to allocate storage within a single segment (although some + compilers simulate linear address spaces on segmented + architectures). On segmented architectures, then, BGET buffer + pools may not be larger than a segment, but since BGET allows any + number of separate buffer pools, there is no limit on the total + storage which can be managed, only on the largest individual + object which can be allocated. Machines with a linear address + architecture, such as the VAX, 680x0, Sparc, MIPS, or the Intel + 80386 and above in native mode, may use BGET without restriction. + + GETTING STARTED WITH BGET + ========================= + + Although BGET can be configured in a multitude of fashions, there + are three basic ways of working with BGET. The functions + mentioned below are documented in the following section. Please + excuse the forward references which are made in the interest of + providing a roadmap to guide you to the BGET functions you're + likely to need. + + Embedded Applications + --------------------- + + Embedded applications typically have a fixed area of memory + dedicated to buffer allocation (often in a separate RAM address + space distinct from the ROM that contains the executable code). + To use BGET in such an environment, simply call bpool() with the + start address and length of the buffer pool area in RAM, then + allocate buffers with bget() and release them with brel(). + Embedded applications with very limited RAM but abundant CPU speed + may benefit by configuring BGET for BestFit allocation (which is + usually not worth it in other environments). + + Malloc() Emulation + ------------------ + + If the C library malloc() function is too slow, not present in + your development environment (for example, an a native Windows or + Macintosh program), or otherwise unsuitable, you can replace it + with BGET. Initially define a buffer pool of an appropriate size + with bpool()--usually obtained by making a call to the operating + system's low-level memory allocator. Then allocate buffers with + bget(), bgetz(), and bgetr() (the last two permit the allocation + of buffers initialised to zero and [inefficient] re-allocation of + existing buffers for compatibility with C library functions). + Release buffers by calling brel(). If a buffer allocation request + fails, obtain more storage from the underlying operating system, + add it to the buffer pool by another call to bpool(), and continue + execution. + + Automatic Storage Management + ---------------------------- + + You can use BGET as your application's native memory manager and + implement automatic storage pool expansion, contraction, and + optionally application-specific memory compaction by compiling + BGET with the BECtl variable defined, then calling bectl() and + supplying functions for storage compaction, acquisition, and + release, as well as a standard pool expansion increment. All of + these functions are optional (although it doesn't make much sense + to provide a release function without an acquisition function, + does it?). Once the call-back functions have been defined with + bectl(), you simply use bget() and brel() to allocate and release + storage as before. You can supply an initial buffer pool with + bpool() or rely on automatic allocation to acquire the entire + pool. When a call on bget() cannot be satisfied, BGET first + checks if a compaction function has been supplied. If so, it is + called (with the space required to satisfy the allocation request + and a sequence number to allow the compaction routine to be called + successively without looping). If the compaction function is able + to free any storage (it needn't know whether the storage it freed + was adequate) it should return a nonzero value, whereupon BGET + will retry the allocation request and, if it fails again, call the + compaction function again with the next-higher sequence number. + + If the compaction function returns zero, indicating failure to + free space, or no compaction function is defined, BGET next tests + whether a non-NULL allocation function was supplied to bectl(). + If so, that function is called with an argument indicating how + many bytes of additional space are required. This will be the + standard pool expansion increment supplied in the call to bectl() + unless the original bget() call requested a buffer larger than + this; buffers larger than the standard pool block can be managed + "off the books" by BGET in this mode. If the allocation function + succeeds in obtaining the storage, it returns a pointer to the new + block and BGET expands the buffer pool; if it fails, the + allocation request fails and returns NULL to the caller. If a + non-NULL release function is supplied, expansion blocks which + become totally empty are released to the global free pool by + passing their addresses to the release function. + + Equipped with appropriate allocation, release, and compaction + functions, BGET can be used as part of very sophisticated memory + management strategies, including garbage collection. (Note, + however, that BGET is *not* a garbage collector by itself, and + that developing such a system requires much additional logic and + careful design of the application's memory allocation strategy.) + + BGET FUNCTION DESCRIPTIONS + ========================== + + Functions implemented in this file (some are enabled by certain of + the optional settings below): + + void bpool(void *buffer, bufsize len); + + Create a buffer pool of bytes, using the storage starting at + . You can call bpool() subsequently to contribute + additional storage to the overall buffer pool. + + void *bget(bufsize size); + + Allocate a buffer of bytes. The address of the buffer is + returned, or NULL if insufficient memory was available to allocate + the buffer. + + void *bgetz(bufsize size); + + Allocate a buffer of bytes and clear it to all zeroes. The + address of the buffer is returned, or NULL if insufficient memory + was available to allocate the buffer. + + void *bgetr(void *buffer, bufsize newsize); + + Reallocate a buffer previously allocated by bget(), changing its + size to and preserving all existing data. NULL is + returned if insufficient memory is available to reallocate the + buffer, in which case the original buffer remains intact. + + void brel(void *buf); + + Return the buffer , previously allocated by bget(), to the + free space pool. + + void bectl(int (*compact)(bufsize sizereq, int sequence), + void *(*acquire)(bufsize size), + void (*release)(void *buf), + bufsize pool_incr); + + Expansion control: specify functions through which the package may + compact storage (or take other appropriate action) when an + allocation request fails, and optionally automatically acquire + storage for expansion blocks when necessary, and release such + blocks when they become empty. If is non-NULL, whenever + a buffer allocation request fails, the function will be + called with arguments specifying the number of bytes (total buffer + size, including header overhead) required to satisfy the + allocation request, and a sequence number indicating the number of + consecutive calls on attempting to satisfy this + allocation request. The sequence number is 1 for the first call + on for a given allocation request, and increments on + subsequent calls, permitting the function to take + increasingly dire measures in an attempt to free up storage. If + the function returns a nonzero value, the allocation + attempt is re-tried. If returns 0 (as it must if it + isn't able to release any space or add storage to the buffer + pool), the allocation request fails, which can trigger automatic + pool expansion if the argument is non-NULL. At the time + the function is called, the state of the buffer + allocator is identical to that at the moment the allocation + request was made; consequently, the function may call + brel(), bpool(), bstats(), and/or directly manipulate the buffer + pool in any manner which would be valid were the application in + control. This does not, however, relieve the function + of the need to ensure that whatever actions it takes do not change + things underneath the application that made the allocation + request. For example, a function that released a buffer + in the process of being reallocated with bgetr() would lead to + disaster. Implementing a safe and effective mechanism + requires careful design of an application's memory architecture, + and cannot generally be easily retrofitted into existing code. + + If is non-NULL, that function will be called whenever an + allocation request fails. If the function succeeds in + allocating the requested space and returns a pointer to the new + area, allocation will proceed using the expanded buffer pool. If + cannot obtain the requested space, it should return NULL + and the entire allocation process will fail. + specifies the normal expansion block size. Providing an + function will cause subsequent bget() requests for buffers too + large to be managed in the linked-block scheme (in other words, + larger than minus the buffer overhead) to be satisfied + directly by calls to the function. Automatic release of + empty pool blocks will occur only if all pool blocks in the system + are the size given by . + + void bstats(bufsize *curalloc, bufsize *totfree, + bufsize *maxfree, long *nget, long *nrel); + + The amount of space currently allocated is stored into the + variable pointed to by . The total free space (sum of + all free blocks in the pool) is stored into the variable pointed + to by , and the size of the largest single block in the + free space pool is stored into the variable pointed to by + . The variables pointed to by and are + filled, respectively, with the number of successful (non-NULL + return) bget() calls and the number of brel() calls. + + void bstatse(bufsize *pool_incr, long *npool, + long *npget, long *nprel, + long *ndget, long *ndrel); + + Extended statistics: The expansion block size will be stored into + the variable pointed to by , or the negative thereof if + automatic expansion block releases are disabled. The number of + currently active pool blocks will be stored into the variable + pointed to by . The variables pointed to by and + will be filled with, respectively, the number of expansion + block acquisitions and releases which have occurred. The + variables pointed to by and will be filled with + the number of bget() and brel() calls, respectively, managed + through blocks directly allocated by the acquisition and release + functions. + + void bufdump(void *buf); + + The buffer pointed to by is dumped on standard output. + + void bpoold(void *pool, int dumpalloc, int dumpfree); + + All buffers in the buffer pool , previously initialised by a + call on bpool(), are listed in ascending memory address order. If + is nonzero, the contents of allocated buffers are + dumped; if is nonzero, the contents of free blocks are + dumped. + + int bpoolv(void *pool); + + The named buffer pool, previously initialised by a call on + bpool(), is validated for bad pointers, overwritten data, etc. If + compiled with NDEBUG not defined, any error generates an assertion + failure. Otherwise 1 is returned if the pool is valid, 0 if an + error is found. + + BGET CONFIGURATION + ================== +*/ + +/* + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ST BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* #define BGET_ENABLE_ALL_OPTIONS */ +#ifdef BGET_ENABLE_OPTION +#define TestProg 20000 /* Generate built-in test program + if defined. The value specifies + how many buffer allocation attempts + the test program should make. */ + +#define SizeQuant 4 /* Buffer allocation size quantum: + all buffers allocated are a + multiple of this size. This + MUST be a power of two. */ + +#define BufDump 1 /* Define this symbol to enable the + bpoold() function which dumps the + buffers in a buffer pool. */ + +#define BufValid 1 /* Define this symbol to enable the + bpoolv() function for validating + a buffer pool. */ + +#define DumpData 1 /* Define this symbol to enable the + bufdump() function which allows + dumping the contents of an allocated + or free buffer. */ + +#define BufStats 1 /* Define this symbol to enable the + bstats() function which calculates + the total free space in the buffer + pool, the largest available + buffer, and the total space + currently allocated. */ + +#define FreeWipe 1 /* Wipe free buffers to a guaranteed + pattern of garbage to trip up + miscreants who attempt to use + pointers into released buffers. */ + +#define BestFit 1 /* Use a best fit algorithm when + searching for space for an + allocation request. This uses + memory more efficiently, but + allocation will be much slower. */ + +#define BECtl 1 /* Define this symbol to enable the + bectl() function for automatic + pool space control. */ +#endif + +#include + +#ifdef lint +#define NDEBUG /* Exits in asserts confuse lint */ + /* LINTLIBRARY: Don't complain about def, no ref */ +extern char *sprintf(); /* Sun includes don't define sprintf */ +#endif + +#include +#include + +#ifdef BufDump /* BufDump implies DumpData */ +#ifndef DumpData +#define DumpData 1 +#endif +#endif + +#ifdef DumpData +#include +#endif + +/* Declare the interface, including the requested buffer size type, + bufsize. */ + +#include "bget.h" + +#define MemSize int /* Type for size arguments to memxxx() + functions such as memcmp(). */ + +/* Queue links */ + +struct qlinks { + struct bfhead *flink; /* Forward link */ + struct bfhead *blink; /* Backward link */ +}; + +/* Header in allocated and free buffers */ + +struct bhead { + bufsize prevfree; /* Relative link back to previous + free buffer in memory or 0 if + previous buffer is allocated. */ + bufsize bsize; /* Buffer size: positive if free, + negative if allocated. */ +}; +#define BH(p) ((struct bhead *)(p)) + +/* Header in directly allocated buffers (by acqfcn) */ + +struct bdhead { + bufsize tsize; /* Total size, including overhead */ + struct bhead bh; /* Common header */ +}; +#define BDH(p) ((struct bdhead *)(p)) + +/* Header in free buffers */ + +struct bfhead { + struct bhead bh; /* Common allocated/free header */ + struct qlinks ql; /* Links on free list */ +}; +#define BFH(p) ((struct bfhead *)(p)) + +struct bfhead freelist = { /* List of free buffers */ + {0, 0}, + {&freelist, &freelist} +}; + +#ifdef BufStats +static bufsize totalloc = 0; /* Total space currently allocated */ +static long numget = 0, numrel = 0; /* Number of bget() and brel() calls */ +#ifdef BECtl +static long numpblk = 0; /* Number of pool blocks */ +static long numpget = 0, numprel = 0; /* Number of block gets and rels */ +static long numdget = 0, numdrel = 0; /* Number of direct gets and rels */ +#endif /* BECtl */ +#endif /* BufStats */ + +#ifdef BECtl + +/* Automatic expansion block management functions */ + +static int (*compfcn) _((bufsize sizereq, int sequence)) = NULL; +static void *(*acqfcn) _((bufsize size)) = NULL; +static void (*relfcn) _((void *buf)) = NULL; + +static bufsize exp_incr = 0; /* Expansion block size */ +static bufsize pool_len = 0; /* 0: no bpool calls have been made + -1: not all pool blocks are + the same size + >0: (common) block size for all + bpool calls made so far + */ +#endif + +/* Minimum allocation quantum: */ + +#define QLSize (sizeof(struct qlinks)) +#define SizeQ ((SizeQuant > QLSize) ? SizeQuant : QLSize) + +#define V (void) /* To denote unwanted returned values */ + +/* End sentinel: value placed in bsize field of dummy block delimiting + end of pool block. The most negative number which will fit in a + bufsize, defined in a way that the compiler will accept. */ + +#define ESent ((bufsize) (-(((1L << (sizeof(bufsize) * 8 - 2)) - 1) * 2) - 2)) + +/* BGET -- Allocate a buffer. */ + +void *bget(requested_size) +bufsize requested_size; +{ + bufsize size = requested_size; + struct bfhead *b; +#ifdef BestFit + struct bfhead *best; +#endif + void *buf; +#ifdef BECtl + int compactseq = 0; +#endif + + assert(size > 0); + + if (size < SizeQ) { /* Need at least room for the */ + size = SizeQ; /* queue links. */ + } +#ifdef SizeQuant +#if SizeQuant > 1 + size = (size + (SizeQuant - 1)) & (~(SizeQuant - 1)); +#endif +#endif + + size += sizeof(struct bhead); /* Add overhead in allocated buffer + to size required. */ + +#ifdef BECtl + /* If a compact function was provided in the call to bectl(), wrap + a loop around the allocation process to allow compaction to + intervene in case we don't find a suitable buffer in the chain. */ + + while (1) { +#endif + b = freelist.ql.flink; +#ifdef BestFit + best = &freelist; +#endif + + /* Scan the free list searching for the first buffer big enough + to hold the requested size buffer. */ + +#ifdef BestFit + while (b != &freelist) { + if (b->bh.bsize >= size) { + if ((best == &freelist) + || (b->bh.bsize < best->bh.bsize)) { + best = b; + } + } + b = b->ql.flink; /* Link to next buffer */ + } + b = best; +#endif /* BestFit */ + + while (b != &freelist) { + if ((bufsize) b->bh.bsize >= size) { + + /* Buffer is big enough to satisfy the request. Allocate it + to the caller. We must decide whether the buffer is large + enough to split into the part given to the caller and a + free buffer that remains on the free list, or whether the + entire buffer should be removed from the free list and + given to the caller in its entirety. We only split the + buffer if enough room remains for a header plus the minimum + quantum of allocation. */ + + if ((b->bh.bsize - size) > + (SizeQ + (sizeof(struct bhead)))) { + struct bhead *ba, *bn; + + ba = BH(((char *)b) + + (b->bh.bsize - size)); + bn = BH(((char *)ba) + size); + assert(bn->prevfree == b->bh.bsize); + /* Subtract size from length of free block. */ + b->bh.bsize -= size; + /* Link allocated buffer to the previous free buffer. */ + ba->prevfree = b->bh.bsize; + /* Plug negative size into user buffer. */ + ba->bsize = -(bufsize) size; + /* Mark buffer after this one not preceded by free block. */ + bn->prevfree = 0; + +#ifdef BufStats + totalloc += size; + numget++; /* Increment number of bget() calls */ +#endif + buf = + (void + *)((((char *)ba) + + sizeof(struct bhead))); + return buf; + } else { + struct bhead *ba; + + ba = BH(((char *)b) + b->bh.bsize); + assert(ba->prevfree == b->bh.bsize); + + /* The buffer isn't big enough to split. Give the whole + shebang to the caller and remove it from the free list. */ + + assert(b->ql.blink->ql.flink == b); + assert(b->ql.flink->ql.blink == b); + b->ql.blink->ql.flink = b->ql.flink; + b->ql.flink->ql.blink = b->ql.blink; + +#ifdef BufStats + totalloc += b->bh.bsize; + numget++; /* Increment number of bget() calls */ +#endif + /* Negate size to mark buffer allocated. */ + b->bh.bsize = -(b->bh.bsize); + + /* Zero the back pointer in the next buffer in memory + to indicate that this buffer is allocated. */ + ba->prevfree = 0; + + /* Give user buffer starting at queue links. */ + buf = (void *)&(b->ql); + return buf; + } + } + b = b->ql.flink; /* Link to next buffer */ + } +#ifdef BECtl + + /* We failed to find a buffer. If there's a compact function + defined, notify it of the size requested. If it returns + TRUE, try the allocation again. */ + + if ((compfcn == NULL) || (!(*compfcn) (size, ++compactseq))) { + break; + } + } + + /* No buffer available with requested size free. */ + + /* Don't give up yet -- look in the reserve supply. */ + + if (acqfcn != NULL) { + if (size > exp_incr - sizeof(struct bhead)) { + + /* Request is too large to fit in a single expansion + block. Try to satisy it by a direct buffer acquisition. */ + + struct bdhead *bdh; + + size += sizeof(struct bdhead) - sizeof(struct bhead); + if ((bdh = BDH((*acqfcn) ((bufsize) size))) != NULL) { + + /* Mark the buffer special by setting the size field + of its header to zero. */ + bdh->bh.bsize = 0; + bdh->bh.prevfree = 0; + bdh->tsize = size; +#ifdef BufStats + totalloc += size; + numget++; /* Increment number of bget() calls */ + numdget++; /* Direct bget() call count */ +#endif + buf = (void *)(bdh + 1); + return buf; + } + + } else { + + /* Try to obtain a new expansion block */ + + void *newpool; + + if ((newpool = (*acqfcn) ((bufsize) exp_incr)) != NULL) { + bpool(newpool, exp_incr); + buf = bget(requested_size); /* This can't, I say, can't + get into a loop. */ + return buf; + } + } + } + + /* Still no buffer available */ + +#endif /* BECtl */ + + return NULL; +} + +/* BGETZ -- Allocate a buffer and clear its contents to zero. We clear + the entire contents of the buffer to zero, not just the + region requested by the caller. */ + +void *bgetz(size) +bufsize size; +{ + char *buf = (char *)bget(size); + + if (buf != NULL) { + struct bhead *b; + bufsize rsize; + + b = BH(buf - sizeof(struct bhead)); + rsize = -(b->bsize); + if (rsize == 0) { + struct bdhead *bd; + + bd = BDH(buf - sizeof(struct bdhead)); + rsize = bd->tsize - sizeof(struct bdhead); + } else { + rsize -= sizeof(struct bhead); + } + assert(rsize >= size); + V memset(buf, 0, (MemSize) rsize); + } + return ((void *)buf); +} + +/* BGETR -- Reallocate a buffer. This is a minimal implementation, + simply in terms of brel() and bget(). It could be + enhanced to allow the buffer to grow into adjacent free + blocks and to avoid moving data unnecessarily. */ + +void *bgetr(buf, size) +void *buf; +bufsize size; +{ + void *nbuf; + bufsize osize; /* Old size of buffer */ + struct bhead *b; + + if ((nbuf = bget(size)) == NULL) { /* Acquire new buffer */ + return NULL; + } + if (buf == NULL) { + return nbuf; + } + b = BH(((char *)buf) - sizeof(struct bhead)); + osize = -b->bsize; +#ifdef BECtl + if (osize == 0) { + /* Buffer acquired directly through acqfcn. */ + struct bdhead *bd; + + bd = BDH(((char *)buf) - sizeof(struct bdhead)); + osize = bd->tsize - sizeof(struct bdhead); + } else +#endif + osize -= sizeof(struct bhead); + assert(osize > 0); + V memcpy((char *)nbuf, (char *)buf, /* Copy the data */ + (MemSize) ((size < osize) ? size : osize)); + brel(buf); + return nbuf; +} + +/* BREL -- Release a buffer. */ + +void brel(buf) +void *buf; +{ + struct bfhead *b, *bn; + + b = BFH(((char *)buf) - sizeof(struct bhead)); +#ifdef BufStats + numrel++; /* Increment number of brel() calls */ +#endif + assert(buf != NULL); + +#ifdef BECtl + if (b->bh.bsize == 0) { /* Directly-acquired buffer? */ + struct bdhead *bdh; + + bdh = BDH(((char *)buf) - sizeof(struct bdhead)); + assert(b->bh.prevfree == 0); +#ifdef BufStats + totalloc -= bdh->tsize; + assert(totalloc >= 0); + numdrel++; /* Number of direct releases */ +#endif /* BufStats */ +#ifdef FreeWipe + V memset((char *)buf, 0x55, + (MemSize) (bdh->tsize - sizeof(struct bdhead))); +#endif /* FreeWipe */ + assert(relfcn != NULL); + (*relfcn) ((void *)bdh); /* Release it directly. */ + return; + } +#endif /* BECtl */ + + /* Buffer size must be negative, indicating that the buffer is + allocated. */ + + if (b->bh.bsize >= 0) { + bn = NULL; + } + assert(b->bh.bsize < 0); + + /* Back pointer in next buffer must be zero, indicating the + same thing: */ + + assert(BH((char *)b - b->bh.bsize)->prevfree == 0); + +#ifdef BufStats + totalloc += b->bh.bsize; + assert(totalloc >= 0); +#endif + + /* If the back link is nonzero, the previous buffer is free. */ + + if (b->bh.prevfree != 0) { + + /* The previous buffer is free. Consolidate this buffer with it + by adding the length of this buffer to the previous free + buffer. Note that we subtract the size in the buffer being + released, since it's negative to indicate that the buffer is + allocated. */ + + register bufsize size = b->bh.bsize; + + /* Make the previous buffer the one we're working on. */ + assert(BH((char *)b - b->bh.prevfree)->bsize == b->bh.prevfree); + b = BFH(((char *)b) - b->bh.prevfree); + b->bh.bsize -= size; + } else { + + /* The previous buffer isn't allocated. Insert this buffer + on the free list as an isolated free block. */ + + assert(freelist.ql.blink->ql.flink == &freelist); + assert(freelist.ql.flink->ql.blink == &freelist); + b->ql.flink = &freelist; + b->ql.blink = freelist.ql.blink; + freelist.ql.blink = b; + b->ql.blink->ql.flink = b; + b->bh.bsize = -b->bh.bsize; + } + + /* Now we look at the next buffer in memory, located by advancing from + the start of this buffer by its size, to see if that buffer is + free. If it is, we combine this buffer with the next one in + memory, dechaining the second buffer from the free list. */ + + bn = BFH(((char *)b) + b->bh.bsize); + if (bn->bh.bsize > 0) { + + /* The buffer is free. Remove it from the free list and add + its size to that of our buffer. */ + + assert(BH((char *)bn + bn->bh.bsize)->prevfree == bn->bh.bsize); + assert(bn->ql.blink->ql.flink == bn); + assert(bn->ql.flink->ql.blink == bn); + bn->ql.blink->ql.flink = bn->ql.flink; + bn->ql.flink->ql.blink = bn->ql.blink; + b->bh.bsize += bn->bh.bsize; + + /* Finally, advance to the buffer that follows the newly + consolidated free block. We must set its backpointer to the + head of the consolidated free block. We know the next block + must be an allocated block because the process of recombination + guarantees that two free blocks will never be contiguous in + memory. */ + + bn = BFH(((char *)b) + b->bh.bsize); + } +#ifdef FreeWipe + V memset(((char *)b) + sizeof(struct bfhead), 0x55, + (MemSize) (b->bh.bsize - sizeof(struct bfhead))); +#endif + assert(bn->bh.bsize < 0); + + /* The next buffer is allocated. Set the backpointer in it to point + to this buffer; the previous free buffer in memory. */ + + bn->bh.prevfree = b->bh.bsize; + +#ifdef BECtl + + /* If a block-release function is defined, and this free buffer + constitutes the entire block, release it. Note that pool_len + is defined in such a way that the test will fail unless all + pool blocks are the same size. */ + + if (relfcn != NULL && + ((bufsize) b->bh.bsize) == (pool_len - sizeof(struct bhead))) { + + assert(b->bh.prevfree == 0); + assert(BH((char *)b + b->bh.bsize)->bsize == ESent); + assert(BH((char *)b + b->bh.bsize)->prevfree == b->bh.bsize); + /* Unlink the buffer from the free list */ + b->ql.blink->ql.flink = b->ql.flink; + b->ql.flink->ql.blink = b->ql.blink; + + (*relfcn) (b); +#ifdef BufStats + numprel++; /* Nr of expansion block releases */ + numpblk--; /* Total number of blocks */ + assert(numpblk == numpget - numprel); +#endif /* BufStats */ + } +#endif /* BECtl */ +} + +#ifdef BECtl + +/* BECTL -- Establish automatic pool expansion control */ + +void bectl(compact, acquire, release, pool_incr) +int (*compact) _((bufsize sizereq, int sequence)); +void *(*acquire) _((bufsize size)); +void (*release) _((void *buf)); +bufsize pool_incr; +{ + compfcn = compact; + acqfcn = acquire; + relfcn = release; + exp_incr = pool_incr; +} +#endif + +/* BPOOL -- Add a region of memory to the buffer pool. */ + +void bpool(buf, len) +void *buf; +bufsize len; +{ + struct bfhead *b = BFH(buf); + struct bhead *bn; + +#ifdef SizeQuant + len &= ~(SizeQuant - 1); +#endif +#ifdef BECtl + if (pool_len == 0) { + pool_len = len; + } else if (len != pool_len) { + pool_len = -1; + } +#ifdef BufStats + numpget++; /* Number of block acquisitions */ + numpblk++; /* Number of blocks total */ + assert(numpblk == numpget - numprel); +#endif /* BufStats */ +#endif /* BECtl */ + + /* Since the block is initially occupied by a single free buffer, + it had better not be (much) larger than the largest buffer + whose size we can store in bhead.bsize. */ + + assert(len - sizeof(struct bhead) <= -((bufsize) ESent + 1)); + + /* Clear the backpointer at the start of the block to indicate that + there is no free block prior to this one. That blocks + recombination when the first block in memory is released. */ + + b->bh.prevfree = 0; + + /* Chain the new block to the free list. */ + + assert(freelist.ql.blink->ql.flink == &freelist); + assert(freelist.ql.flink->ql.blink == &freelist); + b->ql.flink = &freelist; + b->ql.blink = freelist.ql.blink; + freelist.ql.blink = b; + b->ql.blink->ql.flink = b; + + /* Create a dummy allocated buffer at the end of the pool. This dummy + buffer is seen when a buffer at the end of the pool is released and + blocks recombination of the last buffer with the dummy buffer at + the end. The length in the dummy buffer is set to the largest + negative number to denote the end of the pool for diagnostic + routines (this specific value is not counted on by the actual + allocation and release functions). */ + + len -= sizeof(struct bhead); + b->bh.bsize = (bufsize) len; +#ifdef FreeWipe + V memset(((char *)b) + sizeof(struct bfhead), 0x55, + (MemSize) (len - sizeof(struct bfhead))); +#endif + bn = BH(((char *)b) + len); + bn->prevfree = (bufsize) len; + /* Definition of ESent assumes two's complement! */ + assert((~0) == -1); + bn->bsize = ESent; +} + +#ifdef BufStats + +/* BSTATS -- Return buffer allocation free space statistics. */ + +void bstats(curalloc, totfree, maxfree, nget, nrel) +bufsize *curalloc, *totfree, *maxfree; +long *nget, *nrel; +{ + struct bfhead *b = freelist.ql.flink; + + *nget = numget; + *nrel = numrel; + *curalloc = totalloc; + *totfree = 0; + *maxfree = -1; + while (b != &freelist) { + assert(b->bh.bsize > 0); + *totfree += b->bh.bsize; + if (b->bh.bsize > *maxfree) { + *maxfree = b->bh.bsize; + } + b = b->ql.flink; /* Link to next buffer */ + } +} + +#ifdef BECtl + +/* BSTATSE -- Return extended statistics */ + +void bstatse(pool_incr, npool, npget, nprel, ndget, ndrel) +bufsize *pool_incr; +long *npool, *npget, *nprel, *ndget, *ndrel; +{ + *pool_incr = (pool_len < 0) ? -exp_incr : exp_incr; + *npool = numpblk; + *npget = numpget; + *nprel = numprel; + *ndget = numdget; + *ndrel = numdrel; +} +#endif /* BECtl */ +#endif /* BufStats */ + +#ifdef DumpData + +/* BUFDUMP -- Dump the data in a buffer. This is called with the user + data pointer, and backs up to the buffer header. It will + dump either a free block or an allocated one. */ + +void bufdump(buf) +void *buf; +{ + struct bfhead *b; + unsigned char *bdump; + bufsize bdlen; + + b = BFH(((char *)buf) - sizeof(struct bhead)); + assert(b->bh.bsize != 0); + if (b->bh.bsize < 0) { + bdump = (unsigned char *)buf; + bdlen = (-b->bh.bsize) - sizeof(struct bhead); + } else { + bdump = (unsigned char *)(((char *)b) + sizeof(struct bfhead)); + bdlen = b->bh.bsize - sizeof(struct bfhead); + } + + while (bdlen > 0) { + int i, dupes = 0; + bufsize l = bdlen; + char bhex[50], bascii[20]; + + if (l > 16) { + l = 16; + } + + for (i = 0; i < l; i++) { + V snprintf(bhex + i * 3, sizeof(bhex) - i * 3, "%02X ", + bdump[i]); + bascii[i] = isprint(bdump[i]) ? bdump[i] : ' '; + } + bascii[i] = 0; + V printf("%-48s %s\n", bhex, bascii); + bdump += l; + bdlen -= l; + while ((bdlen > 16) && (memcmp((char *)(bdump - 16), + (char *)bdump, 16) == 0)) { + dupes++; + bdump += 16; + bdlen -= 16; + } + if (dupes > 1) { + V printf + (" (%d lines [%d bytes] identical to above line skipped)\n", + dupes, dupes * 16); + } else if (dupes == 1) { + bdump -= 16; + bdlen += 16; + } + } +} +#endif + +#ifdef BufDump + +/* BPOOLD -- Dump a buffer pool. The buffer headers are always listed. + If DUMPALLOC is nonzero, the contents of allocated buffers + are dumped. If DUMPFREE is nonzero, free blocks are + dumped as well. If FreeWipe checking is enabled, free + blocks which have been clobbered will always be dumped. */ + +void bpoold(buf, dumpalloc, dumpfree) +void *buf; +int dumpalloc, dumpfree; +{ + struct bfhead *b = BFH(buf); + + while (b->bh.bsize != ESent) { + bufsize bs = b->bh.bsize; + + if (bs < 0) { + bs = -bs; + V printf("Allocated buffer: size %6ld bytes.\n", + (long)bs); + if (dumpalloc) { + bufdump((void *)(((char *)b) + + sizeof(struct bhead))); + } + } else { + char *lerr = ""; + + assert(bs > 0); + if ((b->ql.blink->ql.flink != b) || + (b->ql.flink->ql.blink != b)) { + lerr = " (Bad free list links)"; + } + V printf("Free block: size %6ld bytes.%s\n", + (long)bs, lerr); +#ifdef FreeWipe + lerr = ((char *)b) + sizeof(struct bfhead); + if ((bs > sizeof(struct bfhead)) && ((*lerr != 0x55) || + (memcmp + (lerr, lerr + 1, + (MemSize) (bs - + (sizeof + (struct + bfhead) + + + 1))) + != 0))) { + V printf + ("(Contents of above free block have been overstored.)\n"); + bufdump((void *)(((char *)b) + + sizeof(struct bhead))); + } else +#endif + if (dumpfree) { + bufdump((void *)(((char *)b) + + sizeof(struct bhead))); + } + } + b = BFH(((char *)b) + bs); + } +} +#endif /* BufDump */ + +#ifdef BufValid + +/* BPOOLV -- Validate a buffer pool. If NDEBUG isn't defined, + any error generates an assertion failure. */ + +int bpoolv(buf) +void *buf; +{ + struct bfhead *b = BFH(buf); + + while (b->bh.bsize != ESent) { + bufsize bs = b->bh.bsize; + + if (bs < 0) { + bs = -bs; + } else { + const char *lerr = ""; + + assert(bs > 0); + if (bs <= 0) { + return 0; + } + if ((b->ql.blink->ql.flink != b) || + (b->ql.flink->ql.blink != b)) { + V printf + ("Free block: size %6ld bytes. (Bad free list links)\n", + (long)bs); + assert(0); + return 0; + } +#ifdef FreeWipe + lerr = ((char *)b) + sizeof(struct bfhead); + if ((bs > sizeof(struct bfhead)) && ((*lerr != 0x55) || + (memcmp + (lerr, lerr + 1, + (MemSize) (bs - + (sizeof + (struct + bfhead) + + + 1))) + != 0))) { + V printf + ("(Contents of above free block have been overstored.)\n"); + bufdump((void *)(((char *)b) + + sizeof(struct bhead))); + assert(0); + return 0; + } +#endif + } + b = BFH(((char *)b) + bs); + } + return 1; +} +#endif /* BufValid */ + + /***********************\ + * * + * Built-in test program * + * * + \***********************/ + +#ifdef TestProg + +#define Repeatable 1 /* Repeatable pseudorandom sequence */ + /* If Repeatable is not defined, a + time-seeded pseudorandom sequence + is generated, exercising BGET with + a different pattern of calls on each + run. */ +#define OUR_RAND /* Use our own built-in version of + rand() to guarantee the test is + 100% repeatable. */ + +#ifdef BECtl +#define PoolSize 300000 /* Test buffer pool size */ +#else +#define PoolSize 50000 /* Test buffer pool size */ +#endif +#define ExpIncr 32768 /* Test expansion block size */ +#define CompactTries 10 /* Maximum tries at compacting */ + +#define dumpAlloc 0 /* Dump allocated buffers ? */ +#define dumpFree 0 /* Dump free buffers ? */ + +#ifndef Repeatable +extern long time(); +#endif + +extern char *malloc(); +extern int free _((char *)); + +static char *bchain = NULL; /* Our private buffer chain */ +static char *bp = NULL; /* Our initial buffer pool */ + +#include + +#ifdef OUR_RAND + +static unsigned long int next = 1; + +/* Return next random integer */ + +int rand() +{ + next = next * 1103515245L + 12345; + return (unsigned int)(next / 65536L) % 32768L; +} + +/* Set seed for random generator */ + +void srand(seed) +unsigned int seed; +{ + next = seed; +} +#endif + +/* STATS -- Edit statistics returned by bstats() or bstatse(). */ + +static void stats(when) +char *when; +{ + bufsize cural, totfree, maxfree; + long nget, nfree; +#ifdef BECtl + bufsize pincr; + long totblocks, npget, nprel, ndget, ndrel; +#endif + + bstats(&cural, &totfree, &maxfree, &nget, &nfree); + V printf + ("%s: %ld gets, %ld releases. %ld in use, %ld free, largest = %ld\n", + when, nget, nfree, (long)cural, (long)totfree, (long)maxfree); +#ifdef BECtl + bstatse(&pincr, &totblocks, &npget, &nprel, &ndget, &ndrel); + V printf + (" Blocks: size = %ld, %ld (%ld bytes) in use, %ld gets, %ld frees\n", + (long)pincr, totblocks, pincr * totblocks, npget, nprel); + V printf(" %ld direct gets, %ld direct frees\n", ndget, ndrel); +#endif /* BECtl */ +} + +#ifdef BECtl +static int protect = 0; /* Disable compaction during bgetr() */ + +/* BCOMPACT -- Compaction call-back function. */ + +static int bcompact(bsize, seq) +bufsize bsize; +int seq; +{ +#ifdef CompactTries + char *bc = bchain; + int i = rand() & 0x3; + +#ifdef COMPACTRACE + V printf("Compaction requested. %ld bytes needed, sequence %d.\n", + (long)bsize, seq); +#endif + + if (protect || (seq > CompactTries)) { +#ifdef COMPACTRACE + V printf("Compaction gave up.\n"); +#endif + return 0; + } + + /* Based on a random cast, release a random buffer in the list + of allocated buffers. */ + + while (i > 0 && bc != NULL) { + bc = *((char **)bc); + i--; + } + if (bc != NULL) { + char *fb; + + fb = *((char **)bc); + if (fb != NULL) { + *((char **)bc) = *((char **)fb); + brel((void *)fb); + return 1; + } + } +#ifdef COMPACTRACE + V printf("Compaction bailed out.\n"); +#endif +#endif /* CompactTries */ + return 0; +} + +/* BEXPAND -- Expand pool call-back function. */ + +static void *bexpand(size) +bufsize size; +{ + void *np = NULL; + bufsize cural, totfree, maxfree; + long nget, nfree; + + /* Don't expand beyond the total allocated size given by PoolSize. */ + + bstats(&cural, &totfree, &maxfree, &nget, &nfree); + + if (cural < PoolSize) { + np = (void *)malloc((unsigned)size); + } +#ifdef EXPTRACE + V printf("Expand pool by %ld -- %s.\n", (long)size, + np == NULL ? "failed" : "succeeded"); +#endif + return np; +} + +/* BSHRINK -- Shrink buffer pool call-back function. */ + +static void bshrink(buf) +void *buf; +{ + if (((char *)buf) == bp) { +#ifdef EXPTRACE + V printf("Initial pool released.\n"); +#endif + bp = NULL; + } +#ifdef EXPTRACE + V printf("Shrink pool.\n"); +#endif + free((char *)buf); +} + +#endif /* BECtl */ + +/* Restrict buffer requests to those large enough to contain our pointer and + small enough for the CPU architecture. */ + +static bufsize blimit(bs) +bufsize bs; +{ + if (bs < sizeof(char *)) { + bs = sizeof(char *); + } + + /* This is written out in this ugly fashion because the + cool expression in sizeof(int) that auto-configured + to any length int befuddled some compilers. */ + + if (sizeof(int) == 2) { + if (bs > 32767) { + bs = 32767; + } + } else { + if (bs > 200000) { + bs = 200000; + } + } + return bs; +} + +int main() +{ + int i; + double x; + + /* Seed the random number generator. If Repeatable is defined, we + always use the same seed. Otherwise, we seed from the clock to + shake things up from run to run. */ + +#ifdef Repeatable + V srand(1234); +#else + V srand((int)time((long *)NULL)); +#endif + + /* Compute x such that pow(x, p) ranges between 1 and 4*ExpIncr as + p ranges from 0 to ExpIncr-1, with a concentration in the lower + numbers. */ + + x = 4.0 * ExpIncr; + x = log(x); + x = exp(log(4.0 * ExpIncr) / (ExpIncr - 1.0)); + +#ifdef BECtl + bectl(bcompact, bexpand, bshrink, (bufsize) ExpIncr); + bp = malloc(ExpIncr); + assert(bp != NULL); + bpool((void *)bp, (bufsize) ExpIncr); +#else + bp = malloc(PoolSize); + assert(bp != NULL); + bpool((void *)bp, (bufsize) PoolSize); +#endif + + stats("Create pool"); + V bpoolv((void *)bp); + bpoold((void *)bp, dumpAlloc, dumpFree); + + for (i = 0; i < TestProg; i++) { + char *cb; + bufsize bs = pow(x, (double)(rand() & (ExpIncr - 1))); + + assert(bs <= (((bufsize) 4) * ExpIncr)); + bs = blimit(bs); + if (rand() & 0x400) { + cb = (char *)bgetz(bs); + } else { + cb = (char *)bget(bs); + } + if (cb == NULL) { +#ifdef EasyOut + break; +#else + char *bc = bchain; + + if (bc != NULL) { + char *fb; + + fb = *((char **)bc); + if (fb != NULL) { + *((char **)bc) = *((char **)fb); + brel((void *)fb); + } + continue; + } +#endif + } + *((char **)cb) = (char *)bchain; + bchain = cb; + + /* Based on a random cast, release a random buffer in the list + of allocated buffers. */ + + if ((rand() & 0x10) == 0) { + char *bc = bchain; + int i = rand() & 0x3; + + while (i > 0 && bc != NULL) { + bc = *((char **)bc); + i--; + } + if (bc != NULL) { + char *fb; + + fb = *((char **)bc); + if (fb != NULL) { + *((char **)bc) = *((char **)fb); + brel((void *)fb); + } + } + } + + /* Based on a random cast, reallocate a random buffer in the list + to a random size */ + + if ((rand() & 0x20) == 0) { + char *bc = bchain; + int i = rand() & 0x3; + + while (i > 0 && bc != NULL) { + bc = *((char **)bc); + i--; + } + if (bc != NULL) { + char *fb; + + fb = *((char **)bc); + if (fb != NULL) { + char *newb; + + bs = pow(x, + (double)(rand() & + (ExpIncr - 1))); + bs = blimit(bs); +#ifdef BECtl + protect = 1; /* Protect against compaction */ +#endif + newb = (char *)bgetr((void *)fb, bs); +#ifdef BECtl + protect = 0; +#endif + if (newb != NULL) { + *((char **)bc) = newb; + } + } + } + } + } + stats("\nAfter allocation"); + if (bp != NULL) { + V bpoolv((void *)bp); + bpoold((void *)bp, dumpAlloc, dumpFree); + } + + while (bchain != NULL) { + char *buf = bchain; + + bchain = *((char **)buf); + brel((void *)buf); + } + stats("\nAfter release"); +#ifndef BECtl + if (bp != NULL) { + V bpoolv((void *)bp); + bpoold((void *)bp, dumpAlloc, dumpFree); + } +#endif + + return 0; +} +#endif diff --git a/lib/libutee/arch/arm32/bget.doc b/lib/libutee/arch/arm32/bget.doc new file mode 100644 index 00000000000..aaa1bd92eda --- /dev/null +++ b/lib/libutee/arch/arm32/bget.doc @@ -0,0 +1,338 @@ + + BGET -- Memory Allocator + ========================== + + by John Walker + http://www.fourmilab.ch/ + +BGET is a comprehensive memory allocation package which is easily +configured to the needs of an application. BGET is efficient in both +the time needed to allocate and release buffers and in the memory +overhead required for buffer pool management. It automatically +consolidates contiguous space to minimise fragmentation. BGET is +configured by compile-time definitions, Major options include: + + * A built-in test program to exercise BGET and + demonstrate how the various functions are used. + + * Allocation by either the "first fit" or "best fit" + method. + + * Wiping buffers at release time to catch code which + references previously released storage. + + * Built-in routines to dump individual buffers or the + entire buffer pool. + + * Retrieval of allocation and pool size statistics. + + * Quantisation of buffer sizes to a power of two to + satisfy hardware alignment constraints. + + * Automatic pool compaction, growth, and shrinkage by + means of call-backs to user defined functions. + +Applications of BGET can range from storage management in ROM-based +embedded programs to providing the framework upon which a multitasking +system incorporating garbage collection is constructed. BGET +incorporates extensive internal consistency checking using the + mechanism; all these checks can be turned off by compiling +with NDEBUG defined, yielding a version of BGET with minimal size and +maximum speed. + +The basic algorithm underlying BGET has withstood the test of time; more +than 25 years have passed since the first implementation of this code. +And yet, it is substantially more efficient than the native allocation +schemes of many operating systems: the Macintosh and Microsoft Windows +to name two, on which programs have obtained substantial speed-ups by +layering BGET as an application level memory manager atop the underlying +system's. + +BGET has been implemented on the largest mainframes and the lowest of +microprocessors. It has served as the core for multitasking operating +systems, multi-thread applications, embedded software in data network +switching processors, and a host of C programs. And while it has +accreted flexibility and additional options over the years, it remains +fast, memory efficient, portable, and easy to integrate into your +program. + + +BGET IMPLEMENTATION ASSUMPTIONS +=============================== + +BGET is written in as portable a dialect of C as possible. The only +fundamental assumption about the underlying hardware architecture is +that memory is allocated is a linear array which can be addressed as a +vector of C "char" objects. On segmented address space architectures, +this generally means that BGET should be used to allocate storage within +a single segment (although some compilers simulate linear address spaces +on segmented architectures). On segmented architectures, then, BGET +buffer pools may not be larger than a segment, but since BGET allows any +number of separate buffer pools, there is no limit on the total storage +which can be managed, only on the largest individual object which can be +allocated. Machines with a linear address architecture, such as the +VAX, 680x0, Sparc, MIPS, or the Intel 80386 and above in native mode, +may use BGET without restriction. + + +GETTING STARTED WITH BGET +========================= + +Although BGET can be configured in a multitude of fashions, there are +three basic ways of working with BGET. The functions mentioned below +are documented in the following section. Please excuse the forward +references which are made in the interest of providing a roadmap to +guide you to the BGET functions you're likely to need. + +Embedded Applications +--------------------- + +Embedded applications typically have a fixed area of memory dedicated to +buffer allocation (often in a separate RAM address space distinct from +the ROM that contains the executable code). To use BGET in such an +environment, simply call bpool() with the start address and length of +the buffer pool area in RAM, then allocate buffers with bget() and +release them with brel(). Embedded applications with very limited RAM +but abundant CPU speed may benefit by configuring BGET for BestFit +allocation (which is usually not worth it in other environments). + +Malloc() Emulation +------------------ + +If the C library malloc() function is too slow, not present in your +development environment (for example, an a native Windows or Macintosh +program), or otherwise unsuitable, you can replace it with BGET. +Initially define a buffer pool of an appropriate size with +bpool()--usually obtained by making a call to the operating system's +low-level memory allocator. Then allocate buffers with bget(), bgetz(), +and bgetr() (the last two permit the allocation of buffers initialised +to zero and [inefficient] re-allocation of existing buffers for +compatibility with C library functions). Release buffers by calling +brel(). If a buffer allocation request fails, obtain more storage from +the underlying operating system, add it to the buffer pool by another +call to bpool(), and continue execution. + +Automatic Storage Management +---------------------------- + +You can use BGET as your application's native memory manager and +implement automatic storage pool expansion, contraction, and optionally +application-specific memory compaction by compiling BGET with the BECtl +variable defined, then calling bectl() and supplying functions for +storage compaction, acquisition, and release, as well as a standard pool +expansion increment. All of these functions are optional (although it +doesn't make much sense to provide a release function without an +acquisition function, does it?). Once the call-back functions have been +defined with bectl(), you simply use bget() and brel() to allocate and +release storage as before. You can supply an initial buffer pool with +bpool() or rely on automatic allocation to acquire the entire pool. +When a call on bget() cannot be satisfied, BGET first checks if a +compaction function has been supplied. If so, it is called (with the +space required to satisfy the allocation request and a sequence number +to allow the compaction routine to be called successively without +looping). If the compaction function is able to free any storage (it +needn't know whether the storage it freed was adequate) it should return +a nonzero value, whereupon BGET will retry the allocation request and, +if it fails again, call the compaction function again with the +next-higher sequence number. + +If the compaction function returns zero, indicating failure to free +space, or no compaction function is defined, BGET next tests whether a +non-NULL allocation function was supplied to bectl(). If so, that +function is called with an argument indicating how many bytes of +additional space are required. This will be the standard pool expansion +increment supplied in the call to bectl() unless the original bget() +call requested a buffer larger than this; buffers larger than the +standard pool block can be managed "off the books" by BGET in this mode. +If the allocation function succeeds in obtaining the storage, it returns +a pointer to the new block and BGET expands the buffer pool; if it +fails, the allocation request fails and returns NULL to the caller. If +a non-NULL release function is supplied, expansion blocks which become +totally empty are released to the global free pool by passing their +addresses to the release function. + +Equipped with appropriate allocation, release, and compaction functions, +BGET can be used as part of very sophisticated memory management +strategies, including garbage collection. (Note, however, that BGET is +*not* a garbage collector by itself, and that developing such a system +requires much additional logic and careful design of the application's +memory allocation strategy.) + + +BGET FUNCTION DESCRIPTIONS +========================== + +Functions implemented by BGET (some are enabled by certain of the +optional settings below): + + void bpool(void *buffer, bufsize len); + +Create a buffer pool of bytes, using the storage starting at +. You can call bpool() subsequently to contribute additional +storage to the overall buffer pool. + + void *bget(bufsize size); + +Allocate a buffer of bytes. The address of the buffer is +returned, or NULL if insufficient memory was available to allocate the +buffer. + + void *bgetz(bufsize size); + +Allocate a buffer of bytes and clear it to all zeroes. The +address of the buffer is returned, or NULL if insufficient memory was +available to allocate the buffer. + + void *bgetr(void *buffer, bufsize newsize); + +Reallocate a buffer previously allocated by bget(), changing its size to + and preserving all existing data. NULL is returned if +insufficient memory is available to reallocate the buffer, in which case +the original buffer remains intact. + + void brel(void *buf); + +Return the buffer , previously allocated by bget(), to the free +space pool. + + void bectl(int (*compact)(bufsize sizereq, int sequence), + void *(*acquire)(bufsize size), + void (*release)(void *buf), + bufsize pool_incr); + +Expansion control: specify functions through which the package may +compact storage (or take other appropriate action) when an allocation +request fails, and optionally automatically acquire storage for +expansion blocks when necessary, and release such blocks when they +become empty. If is non-NULL, whenever a buffer allocation +request fails, the function will be called with arguments +specifying the number of bytes (total buffer size, including header +overhead) required to satisfy the allocation request, and a sequence +number indicating the number of consecutive calls on +attempting to satisfy this allocation request. The sequence number is 1 +for the first call on for a given allocation request, and +increments on subsequent calls, permitting the function to +take increasingly dire measures in an attempt to free up storage. If +the function returns a nonzero value, the allocation attempt +is re-tried. If returns 0 (as it must if it isn't able to +release any space or add storage to the buffer pool), the allocation +request fails, which can trigger automatic pool expansion if the + argument is non-NULL. At the time the function is +called, the state of the buffer allocator is identical to that at the +moment the allocation request was made; consequently, the +function may call brel(), bpool(), bstats(), and/or directly manipulate +the buffer pool in any manner which would be valid were the application +in control. This does not, however, relieve the function of +the need to ensure that whatever actions it takes do not change things +underneath the application that made the allocation request. For +example, a function that released a buffer in the process of +being reallocated with bgetr() would lead to disaster. Implementing a +safe and effective mechanism requires careful design of an +application's memory architecture, and cannot generally be easily +retrofitted into existing code. + +If is non-NULL, that function will be called whenever an +allocation request fails. If the function succeeds in +allocating the requested space and returns a pointer to the new area, +allocation will proceed using the expanded buffer pool. If +cannot obtain the requested space, it should return NULL and the entire +allocation process will fail. specifies the normal +expansion block size. Providing an function will cause +subsequent bget() requests for buffers too large to be managed in the +linked-block scheme (in other words, larger than minus the +buffer overhead) to be satisfied directly by calls to the +function. Automatic release of empty pool blocks will occur only if all +pool blocks in the system are the size given by . + + void bstats(bufsize *curalloc, bufsize *totfree, + bufsize *maxfree, long *nget, long *nrel); + +The amount of space currently allocated is stored into the variable +pointed to by . The total free space (sum of all free blocks +in the pool) is stored into the variable pointed to by , and +the size of the largest single block in the free space pool is stored +into the variable pointed to by . The variables pointed to by + and are filled, respectively, with the number of +successful (non-NULL return) bget() calls and the number of brel() +calls. + + void bstatse(bufsize *pool_incr, long *npool, + long *npget, long *nprel, + long *ndget, long *ndrel); + +Extended statistics: The expansion block size will be stored into the +variable pointed to by , or the negative thereof if automatic +expansion block releases are disabled. The number of currently active +pool blocks will be stored into the variable pointed to by . The +variables pointed to by and will be filled with, +respectively, the number of expansion block acquisitions and releases +which have occurred. The variables pointed to by and +will be filled with the number of bget() and brel() calls, respectively, +managed through blocks directly allocated by the acquisition and release +functions. + + void bufdump(void *buf); + +The buffer pointed to by is dumped on standard output. + + void bpoold(void *pool, int dumpalloc, int dumpfree); + +All buffers in the buffer pool , previously initialised by a call +on bpool(), are listed in ascending memory address order. If + is nonzero, the contents of allocated buffers are dumped; if + is nonzero, the contents of free blocks are dumped. + + int bpoolv(void *pool); + +The named buffer pool, previously initialised by a call on bpool(), is +validated for bad pointers, overwritten data, etc. If compiled with +NDEBUG not defined, any error generates an assertion failure. Otherwise 1 +is returned if the pool is valid, 0 if an error is found. + +BGET CONFIGURATION +================== + +#define TestProg 20000 /* Generate built-in test program + if defined. The value specifies + how many buffer allocation attempts + the test program should make. */ + +#define SizeQuant 4 /* Buffer allocation size quantum: + all buffers allocated are a + multiple of this size. This + MUST be a power of two. */ + +#define BufDump 1 /* Define this symbol to enable the + bpoold() function which dumps the + buffers in a buffer pool. */ + +#define BufValid 1 /* Define this symbol to enable the + bpoolv() function for validating + a buffer pool. */ + +#define DumpData 1 /* Define this symbol to enable the + bufdump() function which allows + dumping the contents of an allocated + or free buffer. */ + +#define BufStats 1 /* Define this symbol to enable the + bstats() function which calculates + the total free space in the buffer + pool, the largest available + buffer, and the total space + currently allocated. */ + +#define FreeWipe 1 /* Wipe free buffers to a guaranteed + pattern of garbage to trip up + miscreants who attempt to use + pointers into released buffers. */ + +#define BestFit 1 /* Use a best fit algorithm when + searching for space for an + allocation request. This uses + memory more efficiently, but + allocation will be much slower. */ + +#define BECtl 1 /* Define this symbol to enable the + bectl() function for automatic + pool space control. */ diff --git a/lib/libutee/arch/arm32/bget.h b/lib/libutee/arch/arm32/bget.h new file mode 100644 index 00000000000..8ffb37e3074 --- /dev/null +++ b/lib/libutee/arch/arm32/bget.h @@ -0,0 +1,43 @@ +/* + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ST BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + + Interface definitions for bget.c, the memory management package. + +*/ + +#ifndef _ +#ifdef PROTOTYPES +#define _(x) x /* If compiler knows prototypes */ +#else +#define _(x) () /* It it doesn't */ +#endif /* PROTOTYPES */ +#endif + +typedef long bufsize; +void bpool _((void *buffer, bufsize len)); +void *bget _((bufsize size)); +void *bgetz _((bufsize size)); +void *bgetr _((void *buffer, bufsize newsize)); +void brel _((void *buf)); +void bectl _((int (*compact) (bufsize sizereq, int sequence), + void *(*acquire) (bufsize size), + void (*release) (void *buf), bufsize pool_incr)); +void bstats _((bufsize *curalloc, bufsize *totfree, bufsize *maxfree, + long *nget, long *nrel)); +void bstatse _((bufsize *pool_incr, long *npool, long *npget, + long *nprel, long *ndget, long *ndrel)); +void bufdump _((void *buf)); +void bpoold _((void *pool, int dumpalloc, int dumpfree)); +int bpoolv _((void *pool)); diff --git a/lib/libutee/arch/arm32/bget_malloc.c b/lib/libutee/arch/arm32/bget_malloc.c new file mode 100644 index 00000000000..8d7342c111e --- /dev/null +++ b/lib/libutee/arch/arm32/bget_malloc.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define PROTOTYPES + +/* + * BGET CONFIGURATION + * ================== + */ +/* #define BGET_ENABLE_ALL_OPTIONS */ +#ifdef BGET_ENABLE_OPTION +#define TestProg 20000 /* Generate built-in test program + if defined. The value specifies + how many buffer allocation attempts + the test program should make. */ +#endif + +#define SizeQuant 4 /* Buffer allocation size quantum: + all buffers allocated are a + multiple of this size. This + MUST be a power of two. */ + +#ifdef BGET_ENABLE_OPTION +#define BufDump 1 /* Define this symbol to enable the + bpoold() function which dumps the + buffers in a buffer pool. */ + +#define BufValid 1 /* Define this symbol to enable the + bpoolv() function for validating + a buffer pool. */ + +#define DumpData 1 /* Define this symbol to enable the + bufdump() function which allows + dumping the contents of an allocated + or free buffer. */ + +#define BufStats 1 /* Define this symbol to enable the + bstats() function which calculates + the total free space in the buffer + pool, the largest available + buffer, and the total space + currently allocated. */ + +#define FreeWipe 1 /* Wipe free buffers to a guaranteed + pattern of garbage to trip up + miscreants who attempt to use + pointers into released buffers. */ + +#define BestFit 1 /* Use a best fit algorithm when + searching for space for an + allocation request. This uses + memory more efficiently, but + allocation will be much slower. */ + +#define BECtl 1 /* Define this symbol to enable the + bectl() function for automatic + pool space control. */ +#endif + +#ifdef MEM_DEBUG +#undef NDEBUG +#define DumpData 1 +#define BufValid 1 +#define FreeWipe 1 +#endif + +#include +#include +#include +#include "bget_malloc.h" +#include "bget.c" /* this is ugly, but this is bget */ +#include + +static void *malloc_heap_buf; +static size_t malloc_heap_len; + +void *calloc(size_t nmemb, size_t size) +{ + return bget_malloc_with_flags(nmemb * size, 0); +} + +void free(void *ptr) +{ +#ifdef BufValid + bpoolv(malloc_heap_buf); +#endif + + if (ptr != NULL) { + uint32_t *flags = ptr; + + flags--; + brel(flags); + } +} + +void *malloc(size_t size) +{ + return bget_malloc_with_flags(size, 0); +} + +void *bget_malloc_with_flags(size_t size, uint32_t flags) +{ + uint32_t *f; + size_t s = size + sizeof(uint32_t); + +#ifdef BufValid + bpoolv(malloc_heap_buf); +#endif + + /* Check wrapping */ + if (s < size) + return NULL; + + f = bget(s); + if (f == NULL) + return NULL; + + *f = flags; + f++; + if (flags == 0) + memset(f, 0, size); + return f; +} + +/* Most of the stuff in this function is copied from bgetr() in bget.c */ +static bufsize bget_buf_size(void *buf) +{ + bufsize osize; /* Old size of buffer */ + struct bhead *b; + + b = BH(((char *)buf) - sizeof(struct bhead)); + osize = -b->bsize; +#ifdef BECtl + if (osize == 0) { + /* Buffer acquired directly through acqfcn. */ + struct bdhead *bd; + + bd = BDH(((char *)buf) - sizeof(struct bdhead)); + osize = bd->tsize - sizeof(struct bdhead); + } else +#endif + osize -= sizeof(struct bhead); + assert(osize > 0); + return osize; +} + +void *realloc(void *ptr, size_t size) +{ + uint32_t *flags = ptr; + size_t s; + + /* + * beause gcc incorrectly assumes this is an uninitialized variable + * not really needed as oszie is only used when memset_required is true + */ + bufsize osize = 0; + bool memset_required = false; + + if (ptr == NULL) + return malloc(size); + + /* increase to include flags word */ + s = size + sizeof(uint32_t); + + /* Check wrapping */ + if (s < size) + return NULL; + + /* decrease to point beginning of allocated buffer */ + flags--; + if (*flags != 0) { + osize = bget_buf_size(flags); + if (osize < s) + memset_required = true; + } + + flags = bgetr(flags, s); + if (flags == NULL) + return NULL; + + if (memset_required) + memset((uint8_t *)flags + osize, 0, s - osize); + + flags++; + return flags; +} + +void bget_malloc_add_heap(void *buf, size_t len) +{ + /* Must not be called twice */ + if (malloc_heap_buf != NULL) + utee_panic(0); + + malloc_heap_buf = buf; + malloc_heap_len = len; + bpool(buf, len); +} + +bool bget_malloc_buffer_is_within_alloced(void *buf, size_t len) +{ + /* A lot of the code is copied from bpoolv() */ + struct bfhead *b = BFH(buf); + uint8_t *ebuf = (uint8_t *)buf + len; + + /* Check for wrapping */ + if ((uint8_t *)buf > ebuf) + return false; + + while (b->bh.bsize != ESent) { + bufsize bs = b->bh.bsize; + + if (bs < 0) { + /* bs < 0 -> We're in an alloced buffer */ + uint8_t *b_data; + + bs = -bs; + b_data = (uint8_t *)b + sizeof(struct bhead); + + if ((uint8_t *)buf >= b_data && ebuf < (b_data + bs)) + return true; + } else { + if (bs == 0) + return false; + } + b = BFH(((char *)b) + bs); + } + + return false; +} + +bool bget_malloc_buffer_overlaps_heap(void *buf, size_t len) +{ + uintptr_t buf_start = (uintptr_t) buf; + uintptr_t buf_end = buf_start + len; + uintptr_t heap_start = (uintptr_t) malloc_heap_buf; + uintptr_t heap_end = heap_start + malloc_heap_len; + + if (buf_start > buf_end || heap_start > heap_end) + return true; /* Wrapping buffers, shouldn't happen */ + + if (buf_end > heap_start || buf_start < heap_end) + return true; + + return false; +} diff --git a/lib/libutee/arch/arm32/bget_malloc.h b/lib/libutee/arch/arm32/bget_malloc.h new file mode 100644 index 00000000000..18f803f3f2a --- /dev/null +++ b/lib/libutee/arch/arm32/bget_malloc.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef BGET_MALLOC_H +#define BGET_MALLOC_H + +void *calloc(size_t nmemb, size_t size); +void free(void *ptr); +void *malloc(size_t size); +void *realloc(void *ptr, size_t size); + +/* + * Adds a pool of memory to allocate from, can currently only be called + * once due to limitation in malloc_buffer_is_within_alloced() + */ +void bget_malloc_add_heap(void *buf, size_t len); + +/* + * Returns true if the supplied memory area is within a buffer + * previously allocated (and not freed yet). + */ +bool bget_malloc_buffer_is_within_alloced(void *buf, size_t len); + +/* + * Returns true if the supplied memory area is overlapping the area used + * for heap. + */ +bool bget_malloc_buffer_overlaps_heap(void *buf, size_t len); + +/* + * Calls allocates a buffer as described in TEE Internal API + * with flags to indicate if malloced memory should be cleared + * or not before return. + */ +void *bget_malloc_with_flags(size_t size, uint32_t flags); + +#endif diff --git a/lib/libutee/arch/arm32/sub.mk b/lib/libutee/arch/arm32/sub.mk new file mode 100644 index 00000000000..dc237a33803 --- /dev/null +++ b/lib/libutee/arch/arm32/sub.mk @@ -0,0 +1,9 @@ +cppflags-y += -I$(sub-dir)/../.. + +srcs-y += bget_malloc.c +cflags-remove-bget_malloc.c-y += -Wold-style-definition -Wredundant-decls +cflags-bget_malloc.c-y += -Wno-sign-compare -Wno-cast-align + +srcs-y += user_ta_entry.c +srcs-y += utee_misc.c +srcs-y += utee_syscalls_asm.S diff --git a/lib/libutee/arch/arm32/user_ta_entry.c b/lib/libutee/arch/arm32/user_ta_entry.c new file mode 100644 index 00000000000..b33b33732cc --- /dev/null +++ b/lib/libutee/arch/arm32/user_ta_entry.c @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "utee_misc.h" +#include + +/* From user_ta_header.c, built within TA */ +extern const size_t ta_data_size; + +/* Exported to user_ta_header.c, built within TA */ + +void ta_entry_close_session(uint32_t session_id) + /*__attribute__((noreturn))*/; + +void ta_entry_open_session(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS], + uint32_t session_id) + /*__attribute__((noreturn))*/; + +void ta_entry_invoke_command(uint32_t cmd_id, uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS], + uint32_t session_id) + /*__attribute__((noreturn))*/; + +/* + * Some external allocation support from libutee or libutils. + */ +void bget_malloc_add_heap(void *buf, size_t len); + +struct ta_session { + uint32_t session_id; + void *session_ctx; + TAILQ_ENTRY(ta_session) link; +}; + +static TAILQ_HEAD(ta_sessions, ta_session) ta_sessions = +TAILQ_HEAD_INITIALIZER(ta_sessions); + +static uint32_t ta_ref_count; +static bool ta_dead; + +extern uint8_t *ta_heap_base; + +uint32_t ta_param_types; +TEE_Param ta_params[TEE_NUM_PARAMS]; + +static void ta_header_save_params(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + ta_param_types = param_types; + if (params != NULL) + memcpy(ta_params, params, sizeof(ta_params)); + else + memset(ta_params, 0, sizeof(ta_params)); +} + +static struct ta_session *ta_header_get_session(uint32_t session_id) +{ + struct ta_session *itr; + TAILQ_FOREACH(itr, &ta_sessions, link) { + if (itr->session_id == session_id) + return itr; + } + return NULL; +} + +static TEE_Result ta_header_add_session(uint32_t session_id) +{ + struct ta_session *itr = ta_header_get_session(session_id); + if (itr != NULL) + return TEE_SUCCESS; + + ta_ref_count++; + + if (ta_ref_count == 1) { + TEE_Result res; + + bget_malloc_add_heap(ta_heap_base, ta_data_size); + + TEE_MathAPI_Init(); + + res = TA_CreateEntryPoint(); + if (res != TEE_SUCCESS) + return res; + } + + itr = + TEE_Malloc(sizeof(struct ta_session), + TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (itr == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + itr->session_id = session_id; + itr->session_ctx = 0; + TAILQ_INSERT_TAIL(&ta_sessions, itr, link); + + return TEE_SUCCESS; +} + +static void ta_header_remove_session(uint32_t session_id) +{ + struct ta_session *itr; + TAILQ_FOREACH(itr, &ta_sessions, link) { + if (itr->session_id == session_id) { + TAILQ_REMOVE(&ta_sessions, itr, link); + TEE_Free(itr); + + ta_ref_count--; + if (ta_ref_count == 0) { + TA_DestroyEntryPoint(); + ta_dead = true; + } + + return; + } + } +} + +void /*__attribute__((noreturn))*/ ta_entry_open_session( + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS], + uint32_t session_id) +{ + TEE_Result res = TEE_ERROR_BAD_STATE; + struct ta_session *session; + + if (ta_dead) + goto function_exit; + + res = ta_header_add_session(session_id); + if (res != TEE_SUCCESS) + goto function_exit; + + session = ta_header_get_session(session_id); + if (session == NULL) + goto function_exit; + + ta_header_save_params(param_types, params); + res = + TA_OpenSessionEntryPoint(param_types, params, + &session->session_ctx); + if (res != TEE_SUCCESS) { + ta_header_remove_session(session_id); + goto function_exit; + } + +function_exit: + ta_header_save_params(0, NULL); + utee_return(res); +} + +void /*__attribute__((noreturn))*/ ta_entry_close_session(uint32_t session_id) +{ + TEE_Result res = TEE_ERROR_BAD_STATE; + struct ta_session *session; + + if (ta_dead) + goto function_exit; + + session = ta_header_get_session(session_id); + if (session == NULL) + goto function_exit; + + TA_CloseSessionEntryPoint(session->session_ctx); + + ta_header_remove_session(session_id); + + res = TEE_SUCCESS; +function_exit: + utee_return(res); +} + +void /*__attribute__((noreturn))*/ ta_entry_invoke_command( + uint32_t cmd_id, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS], + uint32_t session_id) +{ + TEE_Result res = TEE_ERROR_BAD_STATE; + struct ta_session *session; + + if (ta_dead) + goto function_exit; + + session = ta_header_get_session(session_id); + if (session == NULL) + goto function_exit; + + ta_header_save_params(param_types, params); + + res = + TA_InvokeCommandEntryPoint(session->session_ctx, cmd_id, + param_types, params); + +function_exit: + ta_header_save_params(0, NULL); + utee_return(res); +} diff --git a/lib/libutee/arch/arm32/utee_misc.c b/lib/libutee/arch/arm32/utee_misc.c new file mode 100644 index 00000000000..a68615b3709 --- /dev/null +++ b/lib/libutee/arch/arm32/utee_misc.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include + +#include +#include "utee_syscalls.h" + +/* utee_get_ta_exec_id - get a process/thread id for the current sequence */ +unsigned int utee_get_ta_exec_id(void) +{ + /* no execution ID available */ + return 0; +} + +/* utee_malloc/realloc/free - call malloc lib support */ +void *utee_malloc(size_t len) +{ + return malloc(len); +} + +void *utee_realloc(void *buffer, size_t len) +{ + return realloc(buffer, len); +} + +void *utee_calloc(size_t nb, size_t len) +{ + return calloc(len, nb); +} + +void utee_free(void *buffer) +{ + free(buffer); +} + +/* + * This version of get_rng_array() is used by the libmpa, when used on user side + * This is why this function is not implemented in libutee for targets with + * trusted os not split into kernel / user side. In such case, only the + * get_rng_array() version from the kernel side is used. + */ +extern TEE_Result get_rng_array(void *buf, size_t blen); +TEE_Result get_rng_array(void *buf, size_t blen) +{ + return utee_cryp_random_number_generate(buf, blen); +} diff --git a/lib/libutee/arch/arm32/utee_syscalls_asm.S b/lib/libutee/arch/arm32/utee_syscalls_asm.S new file mode 100644 index 00000000000..9a50f4ce2d7 --- /dev/null +++ b/lib/libutee/arch/arm32/utee_syscalls_asm.S @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + + .section .text + .balign 4 + .code 32 + + .macro UTEE_SYSCALL name, scn, num_args + .global \name + .func \name + \name: + + push {r5-r7,lr} + mov r7, #(\scn) + .if \num_args <= 4 + @ No arguments passed on stack + mov r6, #0 + .else + @ Tell number of arguments passed on the stack + mov r6, #(\num_args - 4) + @ Point just before the push (4 registers) above on the first argument + add r5, sp, #(4 * 4) + .endif + svc #0 + pop {r5-r7,pc} + .endfunc + .endm + + UTEE_SYSCALL utee_return, TEE_SCN_RETURN, 1 + + UTEE_SYSCALL utee_log, TEE_SCN_LOG, 2 + + UTEE_SYSCALL utee_panic, TEE_SCN_PANIC, 1 + + UTEE_SYSCALL utee_dummy, TEE_SCN_DUMMY, 1 + + UTEE_SYSCALL utee_dummy_7args, TEE_SCN_DUMMY_7ARGS, 7 + + UTEE_SYSCALL utee_nocall, TEE_SCN_MAX + 1, 0 + + UTEE_SYSCALL utee_get_property, TEE_SCN_GET_PROPERTY, 3 + + UTEE_SYSCALL utee_open_ta_session, TEE_SCN_OPEN_TA_SESSION, 6 + + UTEE_SYSCALL utee_close_ta_session, TEE_SCN_CLOSE_TA_SESSION, 1 + + UTEE_SYSCALL utee_invoke_ta_command, TEE_SCN_INVOKE_TA_COMMAND, 6 + + UTEE_SYSCALL utee_get_cancellation_flag, \ + TEE_SCN_GET_CANCELLATION_FLAG, 0 + + UTEE_SYSCALL utee_check_access_rights, TEE_SCN_CHECK_ACCESS_RIGHTS, 3 + + UTEE_SYSCALL utee_unmask_cancellation, TEE_SCN_UNMASK_CANCELLATION, 0 + + UTEE_SYSCALL utee_mask_cancellation, TEE_SCN_MASK_CANCELLATION, 0 + + UTEE_SYSCALL utee_wait, TEE_SCN_WAIT, 1 + + UTEE_SYSCALL utee_get_time, TEE_SCN_GET_TIME, 2 + + UTEE_SYSCALL utee_set_ta_time, TEE_SCN_SET_TA_TIME, 1 + + UTEE_SYSCALL utee_cryp_state_alloc, TEE_SCN_CRYP_STATE_ALLOC, 5 + + UTEE_SYSCALL utee_cryp_state_copy, TEE_SCN_CRYP_STATE_COPY, 2 + + UTEE_SYSCALL utee_cryp_state_free, TEE_SCN_CRYP_STATE_FREE, 1 + + UTEE_SYSCALL utee_hash_init, TEE_SCN_HASH_INIT, 3 + + UTEE_SYSCALL utee_hash_update, TEE_SCN_HASH_UPDATE, 3 + + UTEE_SYSCALL utee_hash_final, TEE_SCN_HASH_FINAL, 5 + + UTEE_SYSCALL utee_cipher_init, TEE_SCN_CIPHER_INIT, 3 + + UTEE_SYSCALL utee_cipher_update, TEE_SCN_CIPHER_UPDATE, 5 + + UTEE_SYSCALL utee_cipher_final, TEE_SCN_CIPHER_FINAL, 5 + + UTEE_SYSCALL utee_cryp_obj_get_info, TEE_SCN_CRYP_OBJ_GET_INFO, 2 + + UTEE_SYSCALL utee_cryp_obj_restrict_usage, \ + TEE_SCN_CRYP_OBJ_RESTRICT_USAGE, 2 + + UTEE_SYSCALL utee_cryp_obj_get_attr, TEE_SCN_CRYP_OBJ_GET_ATTR, 4 + + UTEE_SYSCALL utee_cryp_obj_alloc, TEE_SCN_CRYP_OBJ_ALLOC, 3 + + UTEE_SYSCALL utee_cryp_obj_close, TEE_SCN_CRYP_OBJ_CLOSE, 1 + + UTEE_SYSCALL utee_cryp_obj_reset, TEE_SCN_CRYP_OBJ_RESET, 1 + + UTEE_SYSCALL utee_cryp_obj_populate, TEE_SCN_CRYP_OBJ_POPULATE, 3 + + UTEE_SYSCALL utee_cryp_obj_copy, TEE_SCN_CRYP_OBJ_COPY, 2 + + UTEE_SYSCALL utee_cryp_derive_key, TEE_SCN_CRYP_DERIVE_KEY, 4 + + UTEE_SYSCALL utee_cryp_random_number_generate, \ + TEE_SCN_CRYP_RANDOM_NUMBER_GENERATE, 2 + + UTEE_SYSCALL utee_authenc_init, TEE_SCN_AUTHENC_INIT, 6 + + UTEE_SYSCALL utee_authenc_update_aad, TEE_SCN_AUTHENC_UPDATE_AAD, 3 + + UTEE_SYSCALL utee_authenc_update_payload, \ + TEE_SCN_AUTHENC_UPDATE_PAYLOAD, 5 + + UTEE_SYSCALL utee_authenc_enc_final, TEE_SCN_AUTHENC_ENC_FINAL, 7 + + UTEE_SYSCALL utee_authenc_dec_final, TEE_SCN_AUTHENC_DEC_FINAL, 7 + + UTEE_SYSCALL utee_asymm_operate, TEE_SCN_ASYMM_OPERATE, 7 + + UTEE_SYSCALL utee_asymm_verify, TEE_SCN_ASYMM_VERIFY, 7 + + UTEE_SYSCALL utee_storage_obj_open, TEE_SCN_STORAGE_OBJ_OPEN, 5 + + UTEE_SYSCALL utee_storage_obj_create, TEE_SCN_STORAGE_OBJ_CREATE, 8 + + UTEE_SYSCALL utee_storage_obj_del, TEE_SCN_STORAGE_OBJ_DEL, 1 + + UTEE_SYSCALL utee_storage_obj_rename, TEE_SCN_STORAGE_OBJ_RENAME, 3 + + UTEE_SYSCALL utee_storage_alloc_enum, TEE_SCN_STORAGE_ENUM_ALLOC, 1 + + UTEE_SYSCALL utee_storage_free_enum, TEE_SCN_STORAGE_ENUM_FREE, 1 + + UTEE_SYSCALL utee_storage_reset_enum, TEE_SCN_STORAGE_ENUM_RESET, 1 + + UTEE_SYSCALL utee_storage_start_enum, TEE_SCN_STORAGE_ENUM_START, 2 + + UTEE_SYSCALL utee_storage_next_enum, TEE_SCN_STORAGE_ENUM_NEXT, 4 + + UTEE_SYSCALL utee_storage_obj_read, TEE_SCN_STORAGE_OBJ_READ, 4 + + UTEE_SYSCALL utee_storage_obj_write, TEE_SCN_STORAGE_OBJ_WRITE, 3 + + UTEE_SYSCALL utee_storage_obj_trunc, TEE_SCN_STORAGE_OBJ_TRUNC, 2 + + UTEE_SYSCALL utee_storage_obj_seek, TEE_SCN_STORAGE_OBJ_SEEK, 3 + + UTEE_SYSCALL utee_cryp_obj_generate_key, \ + TEE_SCN_CRYP_OBJ_GENERATE_KEY, 4 diff --git a/lib/libutee/assert.c b/lib/libutee/assert.c new file mode 100644 index 00000000000..0888f73b7cc --- /dev/null +++ b/lib/libutee/assert.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include + +void _assert_log(const char *expr, const char *file, int line) +{ + EMSG("Assertion '%s' failed at %s:%d", expr, file, line); +} + +void _assert_break(void) +{ + TEE_Panic(TEE_ERROR_GENERIC); +} diff --git a/lib/libutee/base64.c b/lib/libutee/base64.c new file mode 100644 index 00000000000..71291c4d1a7 --- /dev/null +++ b/lib/libutee/base64.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "base64.h" + +static const char base64_table[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +bool base64_enc(const void *data, size_t dlen, char *buf, size_t *blen) +{ + size_t n; + size_t boffs = 0; + const char *d = data; + + n = 4 * ((dlen + 2) / 3) + sizeof('\0'); + if (*blen < n) { + *blen = n; + return false; + } + + for (n = 0; n < dlen; n += 3) { + uint32_t igrp; + + igrp = d[n]; + igrp <<= 8; + + if ((n + 1) < dlen) + igrp |= d[n + 1]; + igrp <<= 8; + + if ((n + 2) < dlen) + igrp |= d[n + 2]; + + buf[boffs] = base64_table[(igrp >> 18) & 0x3f]; + buf[boffs + 1] = base64_table[(igrp >> 12) & 0x3f]; + if ((n + 1) < dlen) + buf[boffs + 2] = base64_table[(igrp >> 6) & 0x3f]; + else + buf[boffs + 2] = '='; + if ((n + 2) < dlen) + buf[boffs + 3] = base64_table[igrp & 0x3f]; + else + buf[boffs + 3] = '='; + + boffs += 4; + } + buf[boffs++] = '\0'; + + *blen = boffs; + return true; +} + +static bool get_idx(char ch, uint8_t *idx) +{ + size_t n; + + for (n = 0; base64_table[n] != '\0'; n++) { + if (ch == base64_table[n]) { + *idx = n; + return true; + } + } + return false; +} + +bool base64_dec(const char *data, size_t size, void *buf, size_t *blen) +{ + size_t n; + uint8_t idx; + uint8_t *b = buf; + size_t m = 0; + size_t s = 0; + + for (n = 0; n < size && data[n] != '\0'; n++) { + if (data[n] == '=') + break; /* Reached pad characters, we're done */ + + if (!get_idx(data[n], &idx)) + continue; + + if (m > *blen) + b = NULL; + + switch (s) { + case 0: + if (b) + b[m] = idx << 2; + s++; + break; + case 1: + if (b) + b[m] |= idx >> 4; + m++; + if (m > *blen) + b = NULL; + if (b) + b[m] = (idx & 0xf) << 4; + s++; + break; + case 2: + if (b) + b[m] |= idx >> 2; + m++; + if (m > *blen) + b = NULL; + if (b) + b[m] = (idx & 0x3) << 6; + s++; + break; + case 3: + if (b) + b[m] |= idx; + m++; + s = 0; + break; + default: + return false; /* "Can't happen" */ + } + } + /* We don't detect if input was bad, but that's OK with the spec. */ + *blen = m; + if (b) + return true; + else + return false; +} diff --git a/lib/libutee/base64.h b/lib/libutee/base64.h new file mode 100644 index 00000000000..86d1880de39 --- /dev/null +++ b/lib/libutee/base64.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef BASE64_H +#define BASE64_H + +#include +#include +#include + +bool base64_enc(const void *data, size_t size, char *buf, size_t *blen); +bool base64_dec(const char *data, size_t size, void *buf, size_t *blen); + +#endif /* BASE64_H */ diff --git a/lib/libutee/errno.c b/lib/libutee/errno.c new file mode 100644 index 00000000000..7147b426997 --- /dev/null +++ b/lib/libutee/errno.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include + +int errno; diff --git a/lib/libutee/include/tee_api.h b/lib/libutee/include/tee_api.h new file mode 100644 index 00000000000..bf69d2b322a --- /dev/null +++ b/lib/libutee/include/tee_api.h @@ -0,0 +1,454 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Based on GP TEE Internal API Specification Version 0.27 */ +#ifndef TEE_API_H +#define TEE_API_H + +#include +#include +#include + +/* Property access functions */ + +TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator, + char *name, char *valueBuffer, + size_t *valueBufferLen); + +TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator, + char *name, bool *value); + +TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator, + char *name, uint32_t *value); + +TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator, + char *name, void *valueBuffer, + size_t *valueBufferLen); + +TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator, + char *name, TEE_UUID *value); + +TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator, + char *name, TEE_Identity *value); + +TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator); + +void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator); + +void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator, + TEE_PropSetHandle propSet); + +void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator); + +TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator, + void *nameBuffer, size_t *nameBufferLen); + +TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator); + +/* System API - Misc */ + +void TEE_Panic(TEE_Result panicCode) +#ifdef __GNUC__ +/* __attribute__((noreturn)) */ +#endif +; + +/* System API - Internal Client API */ + +TEE_Result TEE_OpenTASession(const TEE_UUID *destination, + uint32_t cancellationRequestTimeout, + uint32_t paramTypes, TEE_Param params[4], + TEE_TASessionHandle *session, + uint32_t *returnOrigin); + +void TEE_CloseTASession(TEE_TASessionHandle session); + +TEE_Result TEE_InvokeTACommand(TEE_TASessionHandle session, + uint32_t cancellationRequestTimeout, + uint32_t commandID, uint32_t paramTypes, + TEE_Param params[4], uint32_t *returnOrigin); + +/* System API - Cancellations */ + +bool TEE_GetCancellationFlag(void); + +bool TEE_UnmaskCancellation(void); + +bool TEE_MaskCancellation(void); + +/* System API - Memory Management */ + +TEE_Result TEE_CheckMemoryAccessRights(uint32_t accessFlags, void *buffer, + size_t size); + +void TEE_SetInstanceData(void *instanceData); + +void *TEE_GetInstanceData(void); + +void *TEE_Malloc(size_t size, uint32_t hint); + +void *TEE_Realloc(void *buffer, uint32_t newSize); + +void TEE_Free(void *buffer); + +void *TEE_MemMove(void *dest, const void *src, uint32_t size); + +int32_t TEE_MemCompare(const void *buffer1, const void *buffer2, uint32_t size); + +void *TEE_MemFill(void *buff, uint32_t x, uint32_t size); + +/* Data and Key Storage API - Generic Object Functions */ + +void TEE_GetObjectInfo(TEE_ObjectHandle object, TEE_ObjectInfo *objectInfo); + +void TEE_RestrictObjectUsage(TEE_ObjectHandle object, uint32_t objectUsage); + +TEE_Result TEE_GetObjectBufferAttribute(TEE_ObjectHandle object, + uint32_t attributeID, void *buffer, + size_t *size); + +TEE_Result TEE_GetObjectValueAttribute(TEE_ObjectHandle object, + uint32_t attributeID, uint32_t *a, + uint32_t *b); + +void TEE_CloseObject(TEE_ObjectHandle object); + +/* Data and Key Storage API - Transient Object Functions */ + +TEE_Result TEE_AllocateTransientObject(TEE_ObjectType objectType, + uint32_t maxObjectSize, + TEE_ObjectHandle *object); + +void TEE_FreeTransientObject(TEE_ObjectHandle object); + +void TEE_ResetTransientObject(TEE_ObjectHandle object); + +TEE_Result TEE_PopulateTransientObject(TEE_ObjectHandle object, + TEE_Attribute *attrs, + uint32_t attrCount); + +void TEE_InitRefAttribute(TEE_Attribute *attr, uint32_t attributeID, + void *buffer, size_t length); + +void TEE_InitValueAttribute(TEE_Attribute *attr, uint32_t attributeID, + uint32_t a, uint32_t b); + +void TEE_CopyObjectAttributes(TEE_ObjectHandle destObject, + TEE_ObjectHandle srcObject); + +TEE_Result TEE_GenerateKey(TEE_ObjectHandle object, uint32_t keySize, + TEE_Attribute *params, uint32_t paramCount); + +/* Data and Key Storage API - Persistent Object Functions */ + +TEE_Result TEE_OpenPersistentObject(uint32_t storageID, void *objectID, + size_t objectIDLen, uint32_t flags, + TEE_ObjectHandle *object); + +TEE_Result TEE_CreatePersistentObject(uint32_t storageID, void *objectID, + size_t objectIDLen, uint32_t flags, + TEE_ObjectHandle attributes, + const void *initialData, + size_t initialDataLen, + TEE_ObjectHandle *object); + +void TEE_CloseAndDeletePersistentObject(TEE_ObjectHandle object); + +TEE_Result TEE_RenamePersistentObject(TEE_ObjectHandle object, + const void *newObjectID, + size_t newObjectIDLen); + +TEE_Result TEE_AllocatePersistentObjectEnumerator(TEE_ObjectEnumHandle * + objectEnumerator); + +void TEE_FreePersistentObjectEnumerator(TEE_ObjectEnumHandle objectEnumerator); + +void TEE_ResetPersistentObjectEnumerator(TEE_ObjectEnumHandle objectEnumerator); + +TEE_Result TEE_StartPersistentObjectEnumerator(TEE_ObjectEnumHandle + objectEnumerator, + uint32_t storageID); + +TEE_Result TEE_GetNextPersistentObject(TEE_ObjectEnumHandle objectEnumerator, + TEE_ObjectInfo *objectInfo, + void *objectID, size_t *objectIDLen); + +/* Data and Key Storage API - Data Stream Access Functions */ + +TEE_Result TEE_ReadObjectData(TEE_ObjectHandle object, void *buffer, + size_t size, uint32_t *count); + +TEE_Result TEE_WriteObjectData(TEE_ObjectHandle object, void *buffer, + size_t size); + +TEE_Result TEE_TruncateObjectData(TEE_ObjectHandle object, uint32_t size); + +TEE_Result TEE_SeekObjectData(TEE_ObjectHandle object, int32_t offset, + TEE_Whence whence); + +/* Cryptographic Operations API - Generic Operation Functions */ + +TEE_Result TEE_AllocateOperation(TEE_OperationHandle *operation, + uint32_t algorithm, uint32_t mode, + uint32_t maxKeySize); + +void TEE_FreeOperation(TEE_OperationHandle operation); + +void TEE_GetOperationInfo(TEE_OperationHandle operation, + TEE_OperationInfo *operationInfo); + +void TEE_ResetOperation(TEE_OperationHandle operation); + +TEE_Result TEE_SetOperationKey(TEE_OperationHandle operation, + TEE_ObjectHandle key); + +TEE_Result TEE_SetOperationKey2(TEE_OperationHandle operation, + TEE_ObjectHandle key1, TEE_ObjectHandle key2); + +void TEE_CopyOperation(TEE_OperationHandle dstOperation, + TEE_OperationHandle srcOperation); + +/* Cryptographic Operations API - Message Digest Functions */ + +void TEE_DigestUpdate(TEE_OperationHandle operation, + void *chunk, size_t chunkSize); + +TEE_Result TEE_DigestDoFinal(TEE_OperationHandle operation, const void *chunk, + size_t chunkLen, void *hash, size_t *hashLen); + +/* Cryptographic Operations API - Symmetric Cipher Functions */ + +void TEE_CipherInit(TEE_OperationHandle operation, const void *IV, + size_t IVLen); + +TEE_Result TEE_CipherUpdate(TEE_OperationHandle operation, const void *srcData, + size_t srcLen, void *destData, size_t *destLen); + +TEE_Result TEE_CipherDoFinal(TEE_OperationHandle operation, + const void *srcData, size_t srcLen, void *destData, + size_t *destLen); + +/* Cryptographic Operations API - MAC Functions */ + +void TEE_MACInit(TEE_OperationHandle operation, const void *IV, size_t IVLen); + +void TEE_MACUpdate(TEE_OperationHandle operation, const void *chunk, + size_t chunkSize); + +TEE_Result TEE_MACComputeFinal(TEE_OperationHandle operation, + const void *message, size_t messageLen, + void *mac, size_t *macLen); + +TEE_Result TEE_MACCompareFinal(TEE_OperationHandle operation, + const void *message, size_t messageLen, + const void *mac, size_t macLen); + +/* Cryptographic Operations API - Authenticated Encryption Functions */ + +TEE_Result TEE_AEInit(TEE_OperationHandle operation, const void *nonce, + size_t nonceLen, uint32_t tagLen, uint32_t AADLen, + uint32_t payloadLen); + +void TEE_AEUpdateAAD(TEE_OperationHandle operation, const void *AADdata, + size_t AADdataLen); + +TEE_Result TEE_AEUpdate(TEE_OperationHandle operation, const void *srcData, + size_t srcLen, void *destData, size_t *destLen); + +TEE_Result TEE_AEEncryptFinal(TEE_OperationHandle operation, + const void *srcData, size_t srcLen, + void *destData, size_t *destLen, void *tag, + size_t *tagLen); + +TEE_Result TEE_AEDecryptFinal(TEE_OperationHandle operation, + const void *srcData, size_t srcLen, + void *destData, size_t *destLen, const void *tag, + size_t tagLen); + +/* Cryptographic Operations API - Asymmetric Functions */ + +TEE_Result TEE_AsymmetricEncrypt(TEE_OperationHandle operation, + const TEE_Attribute *params, + uint32_t paramCount, const void *srcData, + size_t srcLen, void *destData, + size_t *destLen); + +TEE_Result TEE_AsymmetricDecrypt(TEE_OperationHandle operation, + const TEE_Attribute *params, + uint32_t paramCount, const void *srcData, + size_t srcLen, void *destData, + size_t *destLen); + +TEE_Result TEE_AsymmetricSignDigest(TEE_OperationHandle operation, + const TEE_Attribute *params, + uint32_t paramCount, const void *digest, + size_t digestLen, void *signature, + size_t *signatureLen); + +TEE_Result TEE_AsymmetricVerifyDigest(TEE_OperationHandle operation, + const TEE_Attribute *params, + uint32_t paramCount, const void *digest, + size_t digestLen, const void *signature, + size_t signatureLen); + +/* Cryptographic Operations API - Key Derivation Functions */ + +void TEE_DeriveKey(TEE_OperationHandle operation, + const TEE_Attribute *params, uint32_t paramCount, + TEE_ObjectHandle derivedKey); + +/* Cryptographic Operations API - Random Number Generation Functions */ + +void TEE_GenerateRandom(void *randomBuffer, size_t randomBufferLen); + +/* Date & Time API */ + +void TEE_GetSystemTime(TEE_Time *time); + +TEE_Result TEE_Wait(uint32_t timeout); + +TEE_Result TEE_GetTAPersistentTime(TEE_Time *time); + +TEE_Result TEE_SetTAPersistentTime(const TEE_Time *time); + +void TEE_GetREETime(TEE_Time *time); + +/* TEE Arithmetical API - Memory allocation and size of objects */ + +size_t TEE_BigIntFMMSizeInU32(size_t modulusSizeInBits); + +size_t TEE_BigIntFMMContextSizeInU32(size_t modulusSizeInBits); + +/* TEE Arithmetical API - Initialization functions */ + +void TEE_BigIntInit(TEE_BigInt *bigInt, size_t len); + +void TEE_BigIntInitFMMContext(TEE_BigIntFMMContext *context, size_t len, + const TEE_BigInt *modulus); + +void TEE_BigIntInitFMM(const TEE_BigIntFMM *bigIntFMM, size_t len); + +/* TEE Arithmetical API - Converter functions */ + +TEE_Result TEE_BigIntConvertFromOctetString(TEE_BigInt *dest, + const uint8_t *buffer, + size_t bufferLen, + int32_t sign); + +TEE_Result TEE_BigIntConvertToOctetString(uint8_t *buffer, size_t *bufferLen, + const TEE_BigInt *bigInt); + +void TEE_BigIntConvertFromS32(TEE_BigInt *dest, int32_t shortVal); + +TEE_Result TEE_BigIntConvertToS32(int32_t *dest, const TEE_BigInt *src); + +void TEE_BigIntSetShort(TEE_BigInt *dest, int32_t shortVal); + +TEE_Result TEE_BigIntGetShort(int32_t *dest, const TEE_BigInt *src); + +/* TEE Arithmetical API - Logical operations */ + +int32_t TEE_BigIntCmp(const TEE_BigInt *op1, const TEE_BigInt *op2); + +int32_t TEE_BigIntCmpS32(const TEE_BigInt *op, int32_t shortVal); + +void TEE_BigIntShiftRight(TEE_BigInt *dest, const TEE_BigInt *op, + size_t bits); + +bool TEE_BigIntGetBit(const TEE_BigInt *src, uint32_t bitIndex); + +uint32_t TEE_BigIntGetBitCount(const TEE_BigInt *src); + +void TEE_BigIntAdd(TEE_BigInt *dest, const TEE_BigInt *op1, + const TEE_BigInt *op2); + +void TEE_BigIntSub(TEE_BigInt *dest, const TEE_BigInt *op1, + const TEE_BigInt *op2); + +void TEE_BigIntNeg(TEE_BigInt *dest, const TEE_BigInt *op); + +void TEE_BigIntMul(TEE_BigInt *dest, const TEE_BigInt *op1, + const TEE_BigInt *op2); + +void TEE_BigIntSquare(TEE_BigInt *dest, const TEE_BigInt *op); + +void TEE_BigIntDiv(TEE_BigInt *dest_q, TEE_BigInt *dest_r, + const TEE_BigInt *op1, const TEE_BigInt *op2); + +void TEE_BigIntReduceMod(TEE_BigInt *dest, const TEE_BigInt *op, + const TEE_BigInt *n); + +/* TEE Arithmetical API - Modular arithmetic operations */ + +void TEE_BigIntMod(TEE_BigInt *dest, const TEE_BigInt *op, + const TEE_BigInt *n); + +void TEE_BigIntAddMod(TEE_BigInt *dest, const TEE_BigInt *op1, + const TEE_BigInt *op2, const TEE_BigInt *n); + +void TEE_BigIntSubMod(TEE_BigInt *dest, const TEE_BigInt *op1, + const TEE_BigInt *op2, const TEE_BigInt *n); + +void TEE_BigIntMulMod(TEE_BigInt *dest, const TEE_BigInt *op1, + const TEE_BigInt *op2, const TEE_BigInt *n); + +void TEE_BigIntSquareMod(TEE_BigInt *dest, const TEE_BigInt *op, + const TEE_BigInt *n); + +void TEE_BigIntInvMod(TEE_BigInt *dest, const TEE_BigInt *op, + const TEE_BigInt *n); + +/* TEE Arithmetical API - Other arithmetic operations */ + +bool TEE_BigIntRelativePrime(const TEE_BigInt *op1, const TEE_BigInt *op2); + +void TEE_BigIntComputeExtendedGcd(TEE_BigInt *gcd, TEE_BigInt *u, + TEE_BigInt *v, const TEE_BigInt *op1, + const TEE_BigInt *op2); + +int32_t TEE_BigIntIsProbablePrime(const TEE_BigInt *op, + uint32_t confidenceLevel); + +/* TEE Arithmetical API - Fast modular multiplication operations */ + +void TEE_BigIntConvertToFMM(TEE_BigIntFMM *dest, const TEE_BigInt *src, + const TEE_BigInt *n, + const TEE_BigIntFMMContext *context); + +void TEE_BigIntConvertFromFMM(TEE_BigInt *dest, const TEE_BigIntFMM *src, + const TEE_BigInt *n, + const TEE_BigIntFMMContext *context); + +void TEE_BigIntFMMConvertToBigInt(TEE_BigInt *dest, const TEE_BigIntFMM *src, + const TEE_BigInt *n, + const TEE_BigIntFMMContext *context); + +void TEE_BigIntComputeFMM(TEE_BigIntFMM *dest, const TEE_BigIntFMM *op1, + const TEE_BigIntFMM *op2, const TEE_BigInt *n, + const TEE_BigIntFMMContext *context); + +#endif /* TEE_API_H */ diff --git a/lib/libutee/include/tee_api_defines.h b/lib/libutee/include/tee_api_defines.h new file mode 100644 index 00000000000..065db28579a --- /dev/null +++ b/lib/libutee/include/tee_api_defines.h @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Based on GP TEE Internal API Specification Version 0.11 */ +#ifndef TEE_API_DEFINES_H +#define TEE_API_DEFINES_H + +#define TEE_HANDLE_NULL 0 + +#define TEE_TIMEOUT_INFINITE 0xFFFFFFFF + +/* API Error Codes */ +#define TEE_SUCCESS 0x00000000 +#define TEE_ERROR_GENERIC 0xFFFF0000 +#define TEE_ERROR_ACCESS_DENIED 0xFFFF0001 +#define TEE_ERROR_CANCEL 0xFFFF0002 +#define TEE_ERROR_ACCESS_CONFLICT 0xFFFF0003 +#define TEE_ERROR_EXCESS_DATA 0xFFFF0004 +#define TEE_ERROR_BAD_FORMAT 0xFFFF0005 +#define TEE_ERROR_BAD_PARAMETERS 0xFFFF0006 +#define TEE_ERROR_BAD_STATE 0xFFFF0007 +#define TEE_ERROR_ITEM_NOT_FOUND 0xFFFF0008 +#define TEE_ERROR_NOT_IMPLEMENTED 0xFFFF0009 +#define TEE_ERROR_NOT_SUPPORTED 0xFFFF000A +#define TEE_ERROR_NO_DATA 0xFFFF000B +#define TEE_ERROR_OUT_OF_MEMORY 0xFFFF000C +#define TEE_ERROR_BUSY 0xFFFF000D +#define TEE_ERROR_COMMUNICATION 0xFFFF000E +#define TEE_ERROR_SECURITY 0xFFFF000F +#define TEE_ERROR_SHORT_BUFFER 0xFFFF0010 +#define TEE_PENDING 0xFFFF2000 +#define TEE_ERROR_TIMEOUT 0xFFFF3001 +#define TEE_ERROR_OVERFLOW 0xFFFF300F +#define TEE_ERROR_TARGET_DEAD 0xFFFF3024 +#define TEE_ERROR_STORAGE_NO_SPACE 0xFFFF3041 +#define TEE_ERROR_MAC_INVALID 0xFFFF3071 +#define TEE_ERROR_SIGNATURE_INVALID 0xFFFF3072 +#define TEE_ERROR_TIME_NOT_SET 0xFFFF5000 +#define TEE_ERROR_TIME_NEEDS_RESET 0xFFFF5001 + +/* + * Proprietary error codes. + * All proprietary error codes should use the 0xF57E prefix. + */ +#define TEE_STE_ERROR_SYSTEM_BUSY 0xF57E0000 +#define TEE_ERROR_FILE_NOT_FOUND 0xF57E0010 + +/* Parameter Type Constants */ +#define TEE_PARAM_TYPE_NONE 0 +#define TEE_PARAM_TYPE_VALUE_INPUT 1 +#define TEE_PARAM_TYPE_VALUE_OUTPUT 2 +#define TEE_PARAM_TYPE_VALUE_INOUT 3 +#define TEE_PARAM_TYPE_MEMREF_INPUT 5 +#define TEE_PARAM_TYPE_MEMREF_OUTPUT 6 +#define TEE_PARAM_TYPE_MEMREF_INOUT 7 + +/* Login Type Constants */ +#define TEE_LOGIN_PUBLIC 0x00000000 +#define TEE_LOGIN_USER 0x00000001 +#define TEE_LOGIN_GROUP 0x00000002 +#define TEE_LOGIN_APPLICATION 0x00000004 +#define TEE_LOGIN_APPLICATION_USER 0x00000005 +#define TEE_LOGIN_APPLICATION_GROUP 0x00000006 +#define TEE_LOGIN_KERNEL 0xA0000000 +#define TEE_LOGIN_TRUSTED_APP 0xF0000000 + +/* Origin Code Constants */ +#define TEE_ORIGIN_API 0x00000001 +#define TEE_ORIGIN_COMMS 0x00000002 +#define TEE_ORIGIN_TEE 0x00000003 +#define TEE_ORIGIN_TRUSTED_APP 0x00000004 + +/* Property Sets pseudo handles */ +#define TEE_PROPSET_CURRENT_TA (TEE_PropSetHandle)0xFFFFFFFF +#define TEE_PROPSET_CURRENT_CLIENT (TEE_PropSetHandle)0xFFFFFFFE +#define TEE_PROPSET_TEE_IMPLEMENTATION (TEE_PropSetHandle)0xFFFFFFFD + +/* Memory Access Rights Constants */ +#define TEE_MEMORY_ACCESS_READ 0x00000001 +#define TEE_MEMORY_ACCESS_WRITE 0x00000002 +#define TEE_MEMORY_ACCESS_ANY_OWNER 0x00000004 + +/* Other constants */ +#define TEE_STORAGE_PRIVATE 0x00000001 +#define TEE_DATA_FLAG_ACCESS_READ 0x00000001 +#define TEE_DATA_FLAG_ACCESS_WRITE 0x00000002 +#define TEE_DATA_FLAG_ACCESS_WRITE_META 0x00000004 +#define TEE_DATA_FLAG_SHARE_READ 0x00000010 +#define TEE_DATA_FLAG_SHARE_WRITE 0x00000020 +#define TEE_DATA_FLAG_CREATE 0x00000200 +#define TEE_DATA_FLAG_EXCLUSIVE 0x00000400 +#define TEE_DATA_MAX_POSITION 0xFFFFFFFF +#define TEE_OBJECT_ID_MAX_LEN 64 +#define TEE_USAGE_EXTRACTABLE 0x00000001 +#define TEE_USAGE_ENCRYPT 0x00000002 +#define TEE_USAGE_DECRYPT 0x00000004 +#define TEE_USAGE_MAC 0x00000008 +#define TEE_USAGE_SIGN 0x00000010 +#define TEE_USAGE_VERIFY 0x00000020 +#define TEE_USAGE_DERIVE 0x00000040 +#define TEE_HANDLE_FLAG_PERSISTENT 0x00010000 +#define TEE_HANDLE_FLAG_INITIALIZED 0x00020000 +#define TEE_HANDLE_FLAG_KEY_SET 0x00040000 +#define TEE_HANDLE_FLAG_EXPECT_TWO_KEYS 0x00080000 +#define TEE_OPERATION_CIPHER 1 +#define TEE_OPERATION_MAC 3 +#define TEE_OPERATION_AE 4 +#define TEE_OPERATION_DIGEST 5 +#define TEE_OPERATION_ASYMMETRIC_CIPHER 6 +#define TEE_OPERATION_ASYMMETRIC_SIGNATURE 7 +#define TEE_OPERATION_KEY_DERIVATION 8 + +/* Algorithm Identifiers */ +#define TEE_ALG_AES_ECB_NOPAD 0x10000010 +#define TEE_ALG_AES_CBC_NOPAD 0x10000110 +#define TEE_ALG_AES_CTR 0x10000210 +#define TEE_ALG_AES_CTS 0x10000310 +#define TEE_ALG_AES_XTS 0x10000410 +#define TEE_ALG_AES_CBC_MAC_NOPAD 0x30000110 +#define TEE_ALG_AES_CBC_MAC_PKCS5 0x30000510 +#define TEE_ALG_AES_CMAC 0x30000610 +#define TEE_ALG_AES_CCM 0x40000710 +#define TEE_ALG_AES_GCM 0x40000810 +#define TEE_ALG_DES_ECB_NOPAD 0x10000011 +#define TEE_ALG_DES_CBC_NOPAD 0x10000111 +#define TEE_ALG_DES_CBC_MAC_NOPAD 0x30000111 +#define TEE_ALG_DES_CBC_MAC_PKCS5 0x30000511 +#define TEE_ALG_DES3_ECB_NOPAD 0x10000013 +#define TEE_ALG_DES3_CBC_NOPAD 0x10000113 +#define TEE_ALG_DES3_CBC_MAC_NOPAD 0x30000113 +#define TEE_ALG_DES3_CBC_MAC_PKCS5 0x30000513 +#define TEE_ALG_RSASSA_PKCS1_V1_5_MD5 0x70001830 +#define TEE_ALG_RSASSA_PKCS1_V1_5_SHA1 0x70002830 +#define TEE_ALG_RSASSA_PKCS1_V1_5_SHA224 0x70003830 +#define TEE_ALG_RSASSA_PKCS1_V1_5_SHA256 0x70004830 +#define TEE_ALG_RSASSA_PKCS1_V1_5_SHA384 0x70005830 +#define TEE_ALG_RSASSA_PKCS1_V1_5_SHA512 0x70006830 +#define TEE_ALG_RSASSA_PKCS1_V1_5_MD5SHA1 0x7000F830 +#define TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1 0x70212930 +#define TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224 0x70313930 +#define TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256 0x70414930 +#define TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384 0x70515930 +#define TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512 0x70616930 +#define TEE_ALG_RSAES_PKCS1_V1_5 0x60000130 +#define TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1 0x60210230 +#define TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224 0x60310230 +#define TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256 0x60410230 +#define TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384 0x60510230 +#define TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512 0x60610230 +#define TEE_ALG_RSA_NOPAD 0x60000030 +#define TEE_ALG_DSA_SHA1 0x70002131 +#define TEE_ALG_DH_DERIVE_SHARED_SECRET 0x80000032 +#define TEE_ALG_MD5 0x50000001 +#define TEE_ALG_SHA1 0x50000002 +#define TEE_ALG_SHA224 0x50000003 +#define TEE_ALG_SHA256 0x50000004 +#define TEE_ALG_SHA384 0x50000005 +#define TEE_ALG_SHA512 0x50000006 +#define TEE_ALG_MD5SHA1 0x5000000F +#define TEE_ALG_HMAC_MD5 0x30000001 +#define TEE_ALG_HMAC_SHA1 0x30000002 +#define TEE_ALG_HMAC_SHA224 0x30000003 +#define TEE_ALG_HMAC_SHA256 0x30000004 +#define TEE_ALG_HMAC_SHA384 0x30000005 +#define TEE_ALG_HMAC_SHA512 0x30000006 + +/* Object Types */ + +#define TEE_TYPE_AES 0xA0000010 +#define TEE_TYPE_DES 0xA0000011 +#define TEE_TYPE_DES3 0xA0000013 +#define TEE_TYPE_HMAC_MD5 0xA0000001 +#define TEE_TYPE_HMAC_SHA1 0xA0000002 +#define TEE_TYPE_HMAC_SHA224 0xA0000003 +#define TEE_TYPE_HMAC_SHA256 0xA0000004 +#define TEE_TYPE_HMAC_SHA384 0xA0000005 +#define TEE_TYPE_HMAC_SHA512 0xA0000006 +#define TEE_TYPE_RSA_PUBLIC_KEY 0xA0000030 +#define TEE_TYPE_RSA_KEYPAIR 0xA1000030 +#define TEE_TYPE_DSA_PUBLIC_KEY 0xA0000031 +#define TEE_TYPE_DSA_KEYPAIR 0xA1000031 +#define TEE_TYPE_DH_KEYPAIR 0xA1000032 +#define TEE_TYPE_GENERIC_SECRET 0xA0000000 + +/* List of Object or Operation Attributes */ + +#define TEE_ATTR_SECRET_VALUE 0xC0000000 +#define TEE_ATTR_RSA_MODULUS 0xD0000130 +#define TEE_ATTR_RSA_PUBLIC_EXPONENT 0xD0000230 +#define TEE_ATTR_RSA_PRIVATE_EXPONENT 0xC0000330 +#define TEE_ATTR_RSA_PRIME1 0xC0000430 +#define TEE_ATTR_RSA_PRIME2 0xC0000530 +#define TEE_ATTR_RSA_EXPONENT1 0xC0000630 +#define TEE_ATTR_RSA_EXPONENT2 0xC0000730 +#define TEE_ATTR_RSA_COEFFICIENT 0xC0000830 +#define TEE_ATTR_DSA_PRIME 0xD0001031 +#define TEE_ATTR_DSA_SUBPRIME 0xD0001131 +#define TEE_ATTR_DSA_BASE 0xD0001231 +#define TEE_ATTR_DSA_PUBLIC_VALUE 0xD0000131 +#define TEE_ATTR_DSA_PRIVATE_VALUE 0xC0000231 +#define TEE_ATTR_DH_PRIME 0xD0001032 +#define TEE_ATTR_DH_SUBPRIME 0xD0001132 +#define TEE_ATTR_DH_BASE 0xD0001232 +#define TEE_ATTR_DH_X_BITS 0xF0001332 +#define TEE_ATTR_DH_PUBLIC_VALUE 0xD0000132 +#define TEE_ATTR_DH_PRIVATE_VALUE 0xC0000232 +#define TEE_ATTR_RSA_OAEP_LABEL 0xD0000930 +#define TEE_ATTR_RSA_PSS_SALT_LENGTH 0xF0000A30 + +/* + * The macro TEE_PARAM_TYPES can be used to construct a value that you can + * compare against an incoming paramTypes to check the type of all the + * parameters in one comparison, like in the following example: + * if (paramTypes != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + * TEE_PARAM_TYPE_MEMREF_OUPUT, + * TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) { + * return TEE_ERROR_BAD_PARAMETERS; + * } + */ +#define TEE_PARAM_TYPES(t0,t1,t2,t3) \ + ((t0) | ((t1) << 4) | ((t2) << 8) | ((t3) << 12)) + +/* + * The macro TEE_PARAM_TYPE_GET can be used to extract the type of a given + * parameter from paramTypes if you need more fine-grained type checking. + */ +#define TEE_PARAM_TYPE_GET(t, i) ((((uint32_t)t) >> ((i)*4)) & 0xF) + +/* + * The macro TEE_PARAM_TYPE_SET can be used to load the type of a given + * parameter from paramTypes without specifying all types (TEE_PARAM_TYPES) + */ +#define TEE_PARAM_TYPE_SET(t, i) (((uint32_t)(t) & 0xF) << ((i)*4)) + +/* Not specified in the standard */ +#define TEE_NUM_PARAMS 4 + +/* TEE Arithmetical APIs */ + +#define TEE_BigIntSizeInU32(n) ((((n)+31)/32)+2) + +#endif /* TEE_API_DEFINES_H */ diff --git a/lib/libutee/include/tee_api_types.h b/lib/libutee/include/tee_api_types.h new file mode 100644 index 00000000000..62c8aada1ce --- /dev/null +++ b/lib/libutee/include/tee_api_types.h @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Based on GP TEE Internal API Specification Version 0.11 */ +#ifndef TEE_API_TYPES_H +#define TEE_API_TYPES_H + +#include +#include +#include +#include + +/* + * Common Definitions + */ + +typedef uint32_t TEE_Result; + +typedef struct { + uint32_t timeLow; + uint16_t timeMid; + uint16_t timeHiAndVersion; + uint8_t clockSeqAndNode[8]; +} TEE_UUID; + +/* + * The TEE_Identity structure defines the full identity of a Client: + * - login is one of the TEE_LOGIN_XXX constants + * - uuid contains the client UUID or Nil if not applicable + */ +typedef struct { + uint32_t login; + TEE_UUID uuid; +} TEE_Identity; + +/* + * This union describes one parameter passed by the Trusted Core Framework + * to the entry points TA_OpenSessionEntryPoint or + * TA_InvokeCommandEntryPoint or by the TA to the functions + * TEE_OpenTASession or TEE_InvokeTACommand. + * + * Which of the field value or memref to select is determined by the + * parameter type specified in the argument paramTypes passed to the entry + * point. +*/ +typedef union { + struct { + void *buffer; + size_t size; + } memref; + struct { + uint32_t a; + uint32_t b; + } value; +} TEE_Param; + +/* + * The type of opaque handles on TA Session. These handles are returned by + * the function TEE_OpenTASession. + */ +typedef struct __TEE_TASessionHandle *TEE_TASessionHandle; + +/* + * The type of opaque handles on property sets or enumerators. These + * handles are either one of the pseudo handles TEE_PROPSET_XXX or are + * returned by the function TEE_AllocatePropertyEnumerator. +*/ +typedef struct __TEE_PropSetHandle *TEE_PropSetHandle; + +typedef struct __TEE_ObjectHandle *TEE_ObjectHandle; +typedef struct __TEE_ObjectEnumHandle *TEE_ObjectEnumHandle; +typedef struct __TEE_OperationHandle *TEE_OperationHandle; + +/* + * Storage Definitions + */ + +typedef uint32_t TEE_ObjectType; + +typedef struct { + uint32_t objectType; + uint32_t objectSize; + uint32_t maxObjectSize; + uint32_t objectUsage; + uint32_t dataSize; + uint32_t dataPosition; + uint32_t handleFlags; +} TEE_ObjectInfo; + +typedef enum { + TEE_DATA_SEEK_SET = 0, + TEE_DATA_SEEK_CUR, + TEE_DATA_SEEK_END +} TEE_Whence; + +typedef struct { + uint32_t attributeID; + union { + struct { + void *buffer; + size_t length; + } ref; + struct { + uint32_t a, b; + } value; + } content; +} TEE_Attribute; + +/* Cryptographic Operations API */ + +typedef enum { + TEE_MODE_ENCRYPT, + TEE_MODE_DECRYPT, + TEE_MODE_SIGN, + TEE_MODE_VERIFY, + TEE_MODE_MAC, + TEE_MODE_DIGEST, + TEE_MODE_DERIVE +} TEE_OperationMode; + +typedef struct { + uint32_t algorithm; + uint32_t operationClass; + uint32_t mode; + uint32_t digestLength; + uint32_t maxKeySize; + uint32_t keySize; + uint32_t requiredKeyUsage; + uint32_t handleState; +} TEE_OperationInfo; + +/* Time & Date API */ + +typedef struct { + uint32_t seconds; + uint32_t millis; +} TEE_Time; + +/* TEE Arithmetical APIs */ + +typedef uint32_t TEE_BigInt; + +typedef uint32_t TEE_BigIntFMM; + +typedef uint32_t TEE_BigIntFMMContext; + +/* Other definitions */ +typedef uint32_t TEE_ErrorOrigin; +typedef void *TEE_Session; + +#define TEE_MEM_INPUT 0x00000001 +#define TEE_MEM_OUTPUT 0x00000002 + +#define TEE_MEMREF_0_USED 0x00000001 +#define TEE_MEMREF_1_USED 0x00000002 +#define TEE_MEMREF_2_USED 0x00000004 +#define TEE_MEMREF_3_USED 0x00000008 + +#endif /* TEE_API_TYPES_H */ diff --git a/lib/libutee/include/tee_arith_internal.h b/lib/libutee/include/tee_arith_internal.h new file mode 100644 index 00000000000..d9f0c1ec210 --- /dev/null +++ b/lib/libutee/include/tee_arith_internal.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef GUARD_TEE_MATHAPI_H +#define GUARD_TEE_MATHAPI_H + +#include /* for size_t */ +#include /* for uint32_t and friends */ +#include /* for bool (!) */ + +/************************************************************* + * + * MACRO DEFINITIONS + * + *************************************************************/ + +/*------------------------------------------------------------ + * + * How functions are exported + * + */ +#define TEE_MATHAPI_EXPORT + +/* + * The modes for String Conversion + */ +#define TEE_STRING_MODE_HEX_UC MPA_STRING_MODE_HEX_UC +#define TEE_STRING_MODE_HEX_LC MPA_STRING_MODE_HEX_UC + +/*------------------------------------------------------------ + * + * Define IN, OUT, INBUF and OUTBUF to keep format from the spec. + * + */ +#define IN const +#define OUT +#define INOUT +#define INBUF const +#define OUTBUF + +/************************************************************* + * + * MEMORY ALLOCATION AND SIZE + * + *************************************************************/ + +/* + * THIS IS THE MAXIMUM NUMBER OF BITS THAT THE LIBRARY SUPPORTS. + * It defines the size of the scratch memory pool for the underlying + * mpa library. + */ +#define TEE_MAX_NUMBER_OF_SUPPORTED_BITS 2048 + +/************************************************************* + * + * INITIALIZATION FUNCTIONS + * + *************************************************************/ + +/* + * !!! This function must be called before you do anything else !!! + * NOTE: Not part of the spec + */ +TEE_MATHAPI_EXPORT void TEE_MathAPI_Init(void); + +#endif diff --git a/lib/libutee/include/tee_internal_api.h b/lib/libutee/include/tee_internal_api.h new file mode 100644 index 00000000000..e3eba8bd0ab --- /dev/null +++ b/lib/libutee/include/tee_internal_api.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Based on GP TEE Internal API Specification Version 0.27 */ +#ifndef TEE_INTERNAL_API_H +#define TEE_INTERNAL_API_H + +#include +#include +#include +#include + +#define SLogTrace(...) +#define SLogError(...) +#define SLogWarning(...) +#define S_VAR_NOT_USED(x) + +#endif diff --git a/lib/libutee/include/tee_internal_api_extensions.h b/lib/libutee/include/tee_internal_api_extensions.h new file mode 100644 index 00000000000..d7a32afd050 --- /dev/null +++ b/lib/libutee/include/tee_internal_api_extensions.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TEE_INTERNAL_API_EXTENSIONS_H +#define TEE_INTERNAL_API_EXTENSIONS_H + +/* trace support */ +#include +int printf(const char *fmt, ...); +int puts(const char *str); + +/* + * User mem module + * + */ +void tee_user_mem_mark_heap(void); +size_t tee_user_mem_check_heap(void); +/* Hint implementation defines */ +#define TEE_USER_MEM_HINT_NO_FILL_ZERO 0x80000000 + +#endif diff --git a/lib/libutee/include/tee_syscall_numbers.h b/lib/libutee/include/tee_syscall_numbers.h new file mode 100644 index 00000000000..91bd21dfe58 --- /dev/null +++ b/lib/libutee/include/tee_syscall_numbers.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TEE_SYSCALL_NUMBERS_H +#define TEE_SYSCALL_NUMBERS_H + +#define TEE_SCN_RETURN 0 +#define TEE_SCN_LOG 1 +#define TEE_SCN_PANIC 2 +#define TEE_SCN_DUMMY 3 +#define TEE_SCN_DUMMY_7ARGS 4 +#define TEE_SCN_GET_PROPERTY 5 +#define TEE_SCN_OPEN_TA_SESSION 6 +#define TEE_SCN_CLOSE_TA_SESSION 7 +#define TEE_SCN_INVOKE_TA_COMMAND 8 +#define TEE_SCN_CHECK_ACCESS_RIGHTS 9 +#define TEE_SCN_GET_CANCELLATION_FLAG 10 +#define TEE_SCN_UNMASK_CANCELLATION 11 +#define TEE_SCN_MASK_CANCELLATION 12 +#define TEE_SCN_WAIT 13 +#define TEE_SCN_GET_TIME 14 +#define TEE_SCN_SET_TA_TIME 15 +#define TEE_SCN_CRYP_STATE_ALLOC 16 +#define TEE_SCN_CRYP_STATE_COPY 17 +#define TEE_SCN_CRYP_STATE_FREE 18 +#define TEE_SCN_HASH_INIT 19 +#define TEE_SCN_HASH_UPDATE 20 +#define TEE_SCN_HASH_FINAL 21 +#define TEE_SCN_CIPHER_INIT 22 +#define TEE_SCN_CIPHER_UPDATE 23 +#define TEE_SCN_CIPHER_FINAL 24 +#define TEE_SCN_CRYP_OBJ_GET_INFO 25 +#define TEE_SCN_CRYP_OBJ_RESTRICT_USAGE 26 +#define TEE_SCN_CRYP_OBJ_GET_ATTR 27 +#define TEE_SCN_CRYP_OBJ_ALLOC 28 +#define TEE_SCN_CRYP_OBJ_CLOSE 29 +#define TEE_SCN_CRYP_OBJ_RESET 30 +#define TEE_SCN_CRYP_OBJ_POPULATE 31 +#define TEE_SCN_CRYP_OBJ_COPY 32 +#define TEE_SCN_CRYP_DERIVE_KEY 33 +#define TEE_SCN_CRYP_RANDOM_NUMBER_GENERATE 34 +#define TEE_SCN_AUTHENC_INIT 35 +#define TEE_SCN_AUTHENC_UPDATE_AAD 36 +#define TEE_SCN_AUTHENC_UPDATE_PAYLOAD 37 +#define TEE_SCN_AUTHENC_ENC_FINAL 38 +#define TEE_SCN_AUTHENC_DEC_FINAL 39 +#define TEE_SCN_ASYMM_OPERATE 40 +#define TEE_SCN_ASYMM_VERIFY 41 +#define TEE_SCN_STORAGE_OBJ_OPEN 42 +#define TEE_SCN_STORAGE_OBJ_CREATE 43 +#define TEE_SCN_STORAGE_OBJ_DEL 44 +#define TEE_SCN_STORAGE_OBJ_RENAME 45 +#define TEE_SCN_STORAGE_ENUM_ALLOC 46 +#define TEE_SCN_STORAGE_ENUM_FREE 47 +#define TEE_SCN_STORAGE_ENUM_RESET 48 +#define TEE_SCN_STORAGE_ENUM_START 49 +#define TEE_SCN_STORAGE_ENUM_NEXT 50 +#define TEE_SCN_STORAGE_OBJ_READ 51 +#define TEE_SCN_STORAGE_OBJ_WRITE 52 +#define TEE_SCN_STORAGE_OBJ_TRUNC 53 +#define TEE_SCN_STORAGE_OBJ_SEEK 54 +#define TEE_SCN_CRYP_OBJ_GENERATE_KEY 55 + +#define TEE_SCN_MAX 55 + +#endif /* TEE_SYSCALL_NUMBERS_H */ diff --git a/lib/libutee/include/tee_ta_api.h b/lib/libutee/include/tee_ta_api.h new file mode 100644 index 00000000000..793486b492d --- /dev/null +++ b/lib/libutee/include/tee_ta_api.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Based on GP TEE Internal API Specification Version 0.22 */ +#ifndef TEE_TA_API_H +#define TEE_TA_API_H + +#include +#include + +/* This is a null define in STE TEE environment */ +#define TA_EXPORT + +/* + * TA Interface + * + * Each Trusted Application must provide the Implementation with a number + * of functions, collectively called the “TA interface”. These functions + * are the entry points called by the Trusted Core Framework to create the + * instance, notify the instance that a new client is connecting, notify + * the instance when the client invokes a command, etc. + * + * Trusted Application Entry Points: + */ + +/* + * The function TA_CreateEntryPoint is the Trusted Application's + * constructor, which the Framework calls when it creates a new instance of + * the Trusted Application. To register instance data, the implementation + * of this constructor can use either global variables or the function + * TEE_InstanceSetData. + * + * Return Value: + * - TEE_SUCCESS: if the instance is successfully created, the function + * must return TEE_SUCCESS. + * - Any other value: if any other code is returned the instance is not + * created, and no other entry points of this instance will be called. + * The Framework MUST reclaim all resources and dereference all objects + * related to the creation of the instance. + * + * If this entry point was called as a result of a client opening a + * session, the error code is returned to the client and the session is + * not opened. + */ +TEE_Result TA_EXPORT TA_CreateEntryPoint(void); + +/* + * The function TA_DestroyEntryPoint is the Trusted Application‟s + * destructor, which the Framework calls when the instance is being + * destroyed. + * + * When the function TA_DestroyEntryPoint is called, the Framework + * guarantees that no client session is currently open. Once the call to + * TA_DestroyEntryPoint has been completed, no other entry point of this + * instance will ever be called. + * + * Note that when this function is called, all resources opened by the + * instance are still available. It is only after the function returns that + * the Implementation MUST start automatically reclaiming resources left + * opened. + * + * Return Value: + * This function can return no success or error code. After this function + * returns the Implementation MUST consider the instance destroyed and + * reclaims all resources left open by the instance. + */ +void TA_EXPORT TA_DestroyEntryPoint(void); + +/* + * The Framework calls the function TA_OpenSessionEntryPoint when a client + * requests to open a session with the Trusted Application. The open + * session request may result in a new Trusted Application instance being + * created as defined in section 4.5. + * + * The client can specify parameters in an open operation which are passed + * to the Trusted Application instance in the arguments paramTypes and + * params. These arguments can also be used by the Trusted Application + * instance to transfer response data back to the client. See section 4.3.6 + * for a specification of how to handle the operation parameters. + * + * If this function returns TEE_SUCCESS, the client is connected to a + * Trusted Application instance and can invoke Trusted Application + * commands. When the client disconnects, the Framework will eventually + * call the TA_CloseSessionEntryPoint entry point. + * + * If the function returns any error, the Framework rejects the connection + * and returns the error code and the current content of the parameters the + * client. The return origin is then set to TEE_ORIGIN_TRUSTED_APP. + * + * The Trusted Application instance can register a session data pointer by + * setting *psessionContext. The value of this pointer is not interpreted + * by the Framework, and is simply passed back to other TA_ functions + * within this session. Note that *sessionContext may be set with a pointer + * to a memory allocated by the Trusted Application instance or with + * anything else, like an integer, a handle etc. The Framework will not + * automatically free *sessionContext when the session is closed; the + * Trusted Application instance is responsible for freeing memory if + * required. + * + * During the call to TA_OpenSessionEntryPoint the client may request to + * cancel the operation. See section 4.10 for more details on + * cancellations. If the call to TA_OpenSessionEntryPoint returns + * TEE_SUCCESS, the client must consider the session as successfully opened + * and explicitly close it if necessary. + * + * Parameters: + * - paramTypes: the types of the four parameters. + * - params: a pointer to an array of four parameters. + * - sessionContext: A pointer to a variable that can be filled by the + * Trusted Application instance with an opaque void* data pointer + * + * Return Value: + * - TEE_SUCCESS if the session is successfully opened. + * - Any other value if the session could not be open. + * o The error code may be one of the pre-defined codes, or may be a new + * error code defined by the Trusted Application implementation itself. + */ +TEE_Result TA_EXPORT TA_OpenSessionEntryPoint(uint32_t paramTypes, + TEE_Param params[4], + void **sessionContext); + +/* + * The Framework calls this function to close a client session. During the + * call to this function the implementation can use any session functions. + * + * The Trusted Application implementation is responsible for freeing any + * resources consumed by the session being closed. Note that the Trusted + * Application cannot refuse to close a session, but can hold the closing + * until it returns from TA_CloseSessionEntryPoint. This is why this + * function cannot return an error code. + * + * Parameters: + * - sessionContext: The value of the void* opaque data pointer set by the + * Trusted Application in the function TA_OpenSessionEntryPoint for this + * session. + */ +void TA_EXPORT TA_CloseSessionEntryPoint(void *sessionContext); + +/* + * The Framework calls this function when the client invokes a command + * within the given session. + * + * The Trusted Application can access the parameters sent by the client + * through the paramTypes and params arguments. It can also use these + * arguments to transfer response data back to the client. + * + * During the call to TA_InvokeCommandEntryPoint the client may request to + * cancel the operation. + * + * A command is always invoked within the context of a client session. + * Thus, any session function can be called by the command implementation. + * + * Parameter: + * - sessionContext: The value of the void* opaque data pointer set by the + * Trusted Application in the function TA_OpenSessionEntryPoint. + * - commandID: A Trusted Application-specific code that identifies the + * command to be invoked. + * - paramTypes: the types of the four parameters. + * - params: a pointer to an array of four parameters. + * + * Return Value: + * - TEE_SUCCESS: if the command is successfully executed, the function + * must return this value. + * - Any other value: if the invocation of the command fails for any + * reason. + * o The error code may be one of the pre-defined codes, or may be a new + * error code defined by the Trusted Application implementation itself. + */ + +TEE_Result TA_EXPORT TA_InvokeCommandEntryPoint(void *sessionContext, + uint32_t commandID, + uint32_t paramTypes, + TEE_Param params[4]); + +/* + * Correspondance Client Functions <--> TA Functions + * + * TEE_OpenSession or TEE_OpenTASession: + * If a new Trusted Application instance is needed to handle the session, + * TA_CreateEntryPoint is called. + * Then, TA_OpenSessionEntryPoint is called. + * + * + * TEE_InvokeCommand or TEE_InvokeTACommand: + * TA_InvokeCommandEntryPoint is called. + * + * + * TEE_CloseSession or TEE_CloseTASession: + * TA_CloseSessionEntryPoint is called. + * For a multi-instance TA or for a single-instance, non keep-alive TA, if + * the session closed was the last session on the instance, then + * TA_DestroyEntryPoint is called. Otherwise, the instance is kept until + * the TEE shuts down. + * + */ + +#endif diff --git a/lib/libutee/include/tee_trace.h b/lib/libutee/include/tee_trace.h new file mode 100644 index 00000000000..e8ac220a97e --- /dev/null +++ b/lib/libutee/include/tee_trace.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_TRACE_H +#define TEE_TRACE_H + +/* + * Trace levels. + * + * ALWAYS is used when you always want a print to be seen, but it is not always + * an error. + * + * ERROR is used when some kind of error has happened, this is most likely the + * print you will use most of the time when you report some kind of error. + * + * INFO is used when you want to print some 'normal' text to the user. + * This is the default level. + * + * DEBUG is used to print extra information to enter deeply in the module. + * + * FLOW is used to print the execution flox, typically the in/out of functions. + * + */ + +#define TRACE_MIN 1 +#define TRACE_ALWAYS TRACE_MIN +#define TRACE_ERROR 2 +#define TRACE_INFO 3 +#define TRACE_DEBUG 4 +#define TRACE_FLOW 5 +#define TRACE_MAX TRACE_FLOW + +/* Trace level of the casual printf */ +#define TRACE_PRINTF_LEVEL TRACE_ALWAYS + +#define MAX_PRINT_SIZE 256 +#define MAX_FUNC_PRINT_SIZE 32 +/* + * This define make sure that parameters are checked in the same manner as it + * is done in the normal printf function. + */ +#define __PRINTFLIKE(__fmt, __varargs) __attribute__\ + ((__format__(__printf__, __fmt, __varargs))) + +/* Trace backend */ +int _dprintf(const char *function, int line, int level, const char *prefix, + const char *fmt, ...) __PRINTFLIKE(5, 6); + +#endif /* TEE_TRACE_H */ diff --git a/lib/libutee/include/tee_uta_trace.h b/lib/libutee/include/tee_uta_trace.h new file mode 100644 index 00000000000..111110ecf63 --- /dev/null +++ b/lib/libutee/include/tee_uta_trace.h @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TEE_UTA_TRACE_H +#define TEE_UTA_TRACE_H + +#include +#include + +/*****************************************************************************/ + +#ifndef STR_TRACE_USER_TA +#define STR_TRACE_USER_TA "USER-TA" +#endif + +#if (CFG_TEE_TA_LOG_LEVEL > 0) +int _dprintf_uta(const char *function, int line, int level, const char *prefix, + const char *fmt, ...) __PRINTFLIKE(5, 6); +#endif + +/*****************************************************************************/ +/* Trace api with trace formatting */ + +/* Filtering and call backend method. + * Retrieve the ta level strored at kernel side by a sys call */ +#define dprintf(level, ...) \ +do { \ + if ((level) <= tahead_get_trace_level()) { \ + _dprintf_uta(__func__, __LINE__, level, STR_TRACE_USER_TA, __VA_ARGS__); \ + } \ +} while (0) + +/* Formmated trace tagged with TRACE_ALWAYS level */ +#if (CFG_TEE_TA_LOG_LEVEL < TRACE_ALWAYS) +#define AMSG(...) (void)0 +#else +#define AMSG(...) _dprintf_uta(__func__, __LINE__, TRACE_ALWAYS, STR_TRACE_USER_TA, __VA_ARGS__); +#endif + +/* Formmated trace tagged with TRACE_ERROR level */ +#if (CFG_TEE_TA_LOG_LEVEL < TRACE_ERROR) +#define EMSG(...) (void)0 +#else +#define EMSG(...) dprintf(TRACE_ERROR, __VA_ARGS__) +#endif + +/* Formmated trace tagged with TRACE_INFO level */ +#if (CFG_TEE_TA_LOG_LEVEL < TRACE_INFO) +#define IMSG(...) (void)0 +#else +#define IMSG(...) dprintf(TRACE_INFO, __VA_ARGS__) +#endif + +/* Formmated trace tagged with TRACE_DEBUG level */ +#if (CFG_TEE_TA_LOG_LEVEL < TRACE_INFO) +#define DMSG(...) (void)0 +#else +#define DMSG(...) dprintf(TRACE_DEBUG, __VA_ARGS__) +#endif + +/* Formmated trace tagged with TRACE_FLOW level */ +#if (CFG_TEE_TA_LOG_LEVEL < TRACE_FLOW) +#define FMSG(...) (void)0 +#else +#define FMSG(...) dprintf(TRACE_FLOW, __VA_ARGS__) +#endif + +/* Formmated trace tagged with TRACE_FLOW level and prefix with '> ' */ +#define INMSG(...) FMSG("> " __VA_ARGS__) +/* Formmated trace tagged with TRACE_FLOW level and prefix with '< ' */ +#define OUTMSG(...) FMSG("< " __VA_ARGS__) +/* Formmated trace tagged with TRACE_FLOW level and prefix with '< ' and print an + * error message if r != 0 */ +#define OUTRMSG(r) \ +do { \ + OUTMSG("r=[%lx]", r); \ + return r; \ +} while (0); + +/*****************************************************************************/ +/* Trace api without trace formatting */ + +/* Filtering and call backend method. + * Retrieve the ta level strored at kernel side by a sys call */ +#define dprintf_raw(level, ...) \ +do { \ + if ((level) <= tahead_get_trace_level()) { \ + _dprintf_uta(NULL, 0, level, STR_TRACE_USER_TA, __VA_ARGS__); \ + } \ +} while (0) + +/* No formatted trace tagged with TRACE_ALWAYS level */ +#if (CFG_TEE_TA_LOG_LEVEL < TRACE_ALWAYS) +#define AMSG_RAW(...) (void)0 +#else +#define AMSG_RAW(...) _dprintf_uta(NULL, 0, TRACE_ALWAYS, STR_TRACE_USER_TA, __VA_ARGS__) +#endif + +/* No formatted trace tagged with TRACE_ERROR level */ +#if (CFG_TEE_TA_LOG_LEVEL < TRACE_ERROR) +#define EMSG_RAW(...) (void)0 +#else +#define EMSG_RAW(...) dprintf_raw(TRACE_ERROR, __VA_ARGS__) +#endif + +/* No formatted trace tagged with TRACE_INFO level */ +#if (CFG_TEE_TA_LOG_LEVEL < TRACE_INFO) +#define IMSG_RAW(...) (void)0 +#else +#define IMSG_RAW(...) dprintf_raw(TRACE_INFO, __VA_ARGS__) +#endif + +/* No formatted trace tagged with TRACE_DEBUG level */ +#if (CFG_TEE_TA_LOG_LEVEL < TRACE_DEBUG) +#define DMSG_RAW(...) (void)0 +#else +#define DMSG_RAW(...) dprintf_raw(TRACE_DEBUG, __VA_ARGS__) +#endif + +/* No formatted trace tagged with TRACE_FLOW level */ +#if (CFG_TEE_TA_LOG_LEVEL < TRACE_FLOW) +#define FMSG(...) (void)0 +#else +#define FMSG_RAW(...) dprintf_raw(TRACE_FLOW, __VA_ARGS__) +#endif + +/*****************************************************************************/ + +#endif /* TEE_UTA_TRACE_H */ diff --git a/lib/libutee/include/user_ta_header.h b/lib/libutee/include/user_ta_header.h new file mode 100644 index 00000000000..0f610ae5fde --- /dev/null +++ b/lib/libutee/include/user_ta_header.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef USER_TA_HEADER_H +#define USER_TA_HEADER_H + +#include + +/* + signed_header + ta_head_t + ta_func_head_t (1) + ta_func_head_t (2) + ... + ta_func_head_t (N) N = ta_head(_t).nbr_func + func_1 + func_1 + ... + func_N + hash_1 + hash_2 + ... + hash_M +*/ + +struct user_ta_head { + TEE_UUID uuid; + uint32_t nbr_func; + uint32_t ro_size; + uint32_t rw_size; + uint32_t zi_size; + uint32_t got_size; + uint32_t hash_type; +}; + +#define USER_TA_HEAD_FLAG_USER_MODE 0x80000000UL +#define USER_TA_HEAD_FLAG_DDR_EXEC 0x40000000UL + +struct user_ta_func_head { + uint32_t cmd_id; + uint32_t start; /* offset to start func */ +}; + +struct user_ta_sub_head { + uint32_t flags; + uint32_t spare; + uint32_t heap_size; + uint32_t stack_size; +}; + +#define TA_FLAG_USER_MODE (1 << 0) +#define TA_FLAG_EXEC_DDR (1 << 1) +#define TA_FLAG_SINGLE_INSTANCE (1 << 2) +#define TA_FLAG_MULTI_SESSION (1 << 3) +#define TA_FLAG_INSTANCE_KEEP_ALIVE (1 << 4) +/* + * TEE Core will allow memrefs in some firewalled memory if this flag is + * set for a User TA. + */ +#define TA_FLAG_UNSAFE_NW_PARAMS (1 << 5) + +enum user_ta_prop_type { + USER_TA_PROP_TYPE_BOOL, /* bool */ + USER_TA_PROP_TYPE_U32, /* uint32_t */ + USER_TA_PROP_TYPE_UUID, /* TEE_UUID */ + USER_TA_PROP_TYPE_IDENTITY, /* TEE_Identity */ + USER_TA_PROP_TYPE_STRING, /* zero terminated string of char */ + USER_TA_PROP_TYPE_BINARY_BLOCK, /* zero terminated base64 coded string */ +}; + +enum user_ta_core_service_id { + USER_TA_CORE_ENTRY_MATH_INIT = 0x00000010, + USER_TA_CORE_ENTRY_GARBAGE = 0x00000011, + USER_TA_CORE_ENTRY_CLOSESESSION = 0x00000012, +}; + +struct user_ta_property { + const char *name; + enum user_ta_prop_type type; + const void *value; +}; + +extern const struct user_ta_property ta_props[]; +extern const size_t ta_num_props; + +/* Needed by TEE_CheckMemoryAccessRights() */ +extern uint32_t ta_param_types; +extern TEE_Param ta_params[4]; + +/* Trusted Application Function header */ +typedef struct ta_func_head { + uint32_t cmd_id; /* Trusted Application Function ID */ + uint32_t start; /* offset to start func */ +} ta_func_head_t; + +typedef struct { + /* Same Prefix as ta_head_t */ + TEE_UUID uuid; + const char *name; + uint32_t flags; + + /* properties */ + uint32_t prop_datasize; + uint32_t prop_stacksize; + uint32_t prop_tracelevel; + + const ta_func_head_t *funcs; + uint32_t nbr_func; + TEE_Result(*create_entry_point) (void); + void (*destroy_entry_point) (void); + TEE_Result(*open_session_entry_point) (uint32_t nParamTypes, + TEE_Param pParams[4], + void **ppSessionContext); + void (*close_session_entry_point) (void *pSessionContext); + TEE_Result(*invoke_command_entry_point) (void *pSessionContext, + uint32_t nCommandID, + uint32_t nParamTypes, + TEE_Param pParams[4]); + TEE_Result(*core_entries) (uint32_t nServiceId, uint32_t nParamTypes, + TEE_Param pParam[4]); +} ta_static_head_t; + +int tahead_get_trace_level(void); + +#endif /* USER_TA_HEADER_H */ diff --git a/lib/libutee/include/utee_defines.h b/lib/libutee/include/utee_defines.h new file mode 100644 index 00000000000..05afc6c7117 --- /dev/null +++ b/lib/libutee/include/utee_defines.h @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef UTEE_DEFINES_H +#define UTEE_DEFINES_H + +/* + * Copied from TEE Internal API specificaion v1.0 table 6-9 "Structure of + * Algorithm Identifier". + */ +#define TEE_MAIN_ALGO_MD5 0x01 +#define TEE_MAIN_ALGO_SHA1 0x02 +#define TEE_MAIN_ALGO_SHA224 0x03 +#define TEE_MAIN_ALGO_SHA256 0x04 +#define TEE_MAIN_ALGO_SHA384 0x05 +#define TEE_MAIN_ALGO_SHA512 0x06 +#define TEE_MAIN_ALGO_AES 0x10 +#define TEE_MAIN_ALGO_DES 0x11 +#define TEE_MAIN_ALGO_DES2 0x12 +#define TEE_MAIN_ALGO_DES3 0x13 +#define TEE_MAIN_ALGO_RSA 0x30 +#define TEE_MAIN_ALGO_DSA 0x31 +#define TEE_MAIN_ALGO_DH 0x32 + +#define TEE_CHAIN_MODE_ECB_NOPAD 0x0 +#define TEE_CHAIN_MODE_CBC_NOPAD 0x1 +#define TEE_CHAIN_MODE_CTR 0x2 +#define TEE_CHAIN_MODE_CTS 0x3 +#define TEE_CHAIN_MODE_XTS 0x4 +#define TEE_CHAIN_MODE_CBC_MAC_PKCS5 0x5 +#define TEE_CHAIN_MODE_CMAC 0x6 +#define TEE_CHAIN_MODE_CCM 0x7 +#define TEE_CHAIN_MODE_GCM 0x8 +#define TEE_CHAIN_MODE_PKCS1_PSS_MGF1 0x9 /* ??? */ + + /* Bits [31:28] */ +#define TEE_ALG_GET_CLASS(algo) (((algo) >> 28) & 0xF) + +#define TEE_ALG_GET_KEY_TYPE(algo, with_private_key) \ + (TEE_ALG_GET_MAIN_ALG(algo) | \ + ((with_private_key) ? 0xA1000000 : 0xA0000000)) + + /* Bits [7:0] */ +#define TEE_ALG_GET_MAIN_ALG(algo) ((algo) & 0xFF) + + /* Bits [11:8] */ +#define TEE_ALG_GET_CHAIN_MODE(algo) (((algo) >> 8) & 0xF) + + /* Bits [15:12] */ +#define TEE_ALG_GET_DIGEST_HASH(algo) (((algo) >> 12) & 0xF) + + /* Bits [23:20] */ +#define TEE_ALG_GET_INTERNAL_HASH(algo) (((algo) >> 20) & 0x7) + + /* Return hash algorithm based on main hash */ +#define TEE_ALG_HASH_ALGO(main_hash) \ + (TEE_OPERATION_DIGEST << 28 | (main_hash)) + + /* Extract internal hash and return hash algorithm */ +#define TEE_INTERNAL_HASH_TO_ALGO(algo) \ + TEE_ALG_HASH_ALGO(TEE_ALG_GET_INTERNAL_HASH(algo)) + + /* Extract digest hash and return hash algorithm */ +#define TEE_DIGEST_HASH_TO_ALGO(algo) \ + TEE_ALG_HASH_ALGO(TEE_ALG_GET_DIGEST_HASH(algo)) + +#define TEE_AES_BLOCK_SIZE 16UL +#define TEE_DES_BLOCK_SIZE 8UL + +#define TEE_AES_MAX_KEY_SIZE 32UL + + /* SHA-512 */ +#ifndef TEE_MD5_HASH_SIZE +typedef enum { + TEE_MD5_HASH_SIZE = 16, + TEE_SHA1_HASH_SIZE = 20, + TEE_SHA224_HASH_SIZE = 28, + TEE_SHA256_HASH_SIZE = 32, + TEE_SHA384_HASH_SIZE = 48, + TEE_SHA512_HASH_SIZE = 64, + TEE_MD5SHA1_HASH_SIZE = (TEE_MD5_HASH_SIZE + TEE_SHA1_HASH_SIZE), + TEE_MAX_HASH_SIZE = 64, +} t_hash_size; +#endif + +#define TEE_MAC_SIZE_AES_CBC_MAC_NOPAD +#define TEE_MAC_SIZE_AES_CBC_MAC_PKCS5 +#define TEE_MAC_SIZE_AES_CMAC +#define TEE_MAC_SIZE_DES_CBC_MAC_PKCS5 + +/* + * Bit indicating that the attribute is a value attribute + * See TEE Internal API specificaion v1.0 table 6-12 "Partial Structure of + * Attribute Identifier" + */ +#define TEE_ATTR_BIT_VALUE (1 << 29) + +#ifndef MAX +#define MAX(a, b) \ + __extension__({ __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a > _b ? _a : _b; }) + +#define MIN(a, b) \ + __extension__({ __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a < _b ? _a : _b; }) +#endif + +/* Round up the even multiple of size, size has to be a multiple of 2 */ +#define TEE_ROUNDUP(v, size) (((v) + (size - 1)) & ~(size - 1)) + +/* Round down the even multiple of size, size has to be a multiple of 2 */ +#define TEE_ROUNDDOWN(v, size) ((v) & ~(size - 1)) + +#define TEE_U32_BSWAP(x) ( \ + (((x) & 0xff000000) >> 24) | \ + (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | \ + (((x) & 0x000000ff) << 24)) + +#define TEE_U16_BSWAP(x) ( \ + (((x) & 0xff00) >> 8) | \ + (((x) & 0x00ff) << 8)) + +/* If we we're on a big endian platform we'll have to update these */ +#define TEE_U32_FROM_BIG_ENDIAN(x) TEE_U32_BSWAP(x) +#define TEE_U16_FROM_BIG_ENDIAN(x) TEE_U16_BSWAP(x) +#define TEE_U32_TO_BIG_ENDIAN(x) TEE_U32_BSWAP(x) +#define TEE_U16_TO_BIG_ENDIAN(x) TEE_U16_BSWAP(x) + +#ifndef TEE_ALIGNMENT_IS_OK +#ifdef CFG_TC_NO_ALIGNOF +#define TEE_ALIGNMENT_1B_IS_OK(p, type) (true) +#define TEE_ALIGNMENT_2B_IS_OK(p, type) (((((unsigned long)&(p)) & 1) == 0) ? true : false) +#define TEE_ALIGNMENT_4B_IS_OK(p, type) (((((unsigned long)&(p)) & 3) == 0) ? true : false) +#define TEE_ALIGNMENT_8B_IS_OK(p, type) (((((unsigned long)&(p)) & 7) == 0) ? true : false) +#define TEE_ALIGNMENT_IS_OK(p, type) TEE_ALIGNMENT_4B_IS_OK(p, type) +#else +#define TEE_ALIGNMENT_1B_IS_OK(p, type) TEE_ALIGNMENT_WRAP_IS_OK(p, type) +#define TEE_ALIGNMENT_2B_IS_OK(p, type) TEE_ALIGNMENT_WRAP_IS_OK(p, type) +#define TEE_ALIGNMENT_4B_IS_OK(p, type) TEE_ALIGNMENT_WRAP_IS_OK(p, type) +#define TEE_ALIGNMENT_8B_IS_OK(p, type) TEE_ALIGNMENT_WRAP_IS_OK(p, type) +#define TEE_ALIGNMENT_IS_OK(p, type) TEE_ALIGNMENT_WRAP_IS_OK(p, type) + +#define TEE_ALIGNMENT_WRAP_IS_OK(p, type) \ + (((uintptr_t)p & (__tee_assert_alignof__(type) - 1)) == 0) + +#define __tee_assert_alignof__(type) __alignof__(type) +#endif +#endif + +#define TEE_TIME_MILLIS_BASE 1000 + +#define TEE_TIME_LT(t1, t2) \ + (((t1).seconds == (t2).seconds) ? \ + ((t1).millis < (t2).millis) : \ + ((t1).seconds < (t2).seconds)) + +#define TEE_TIME_LE(t1, t2) \ + (((t1).seconds == (t2).seconds) ? \ + ((t1).millis <= (t2).millis) : \ + ((t1).seconds <= (t2).seconds)) + +#define TEE_TIME_ADD(t1, t2, dst) do { \ + (dst).seconds = (t1).seconds + (t2).seconds; \ + (dst).millis = (t1).millis + (t2).millis; \ + if ((dst).millis >= TEE_TIME_MILLIS_BASE) { \ + (dst).seconds++; \ + (dst).millis -= TEE_TIME_MILLIS_BASE; \ + } \ + } while (0) + +#define TEE_TIME_SUB(t1, t2, dst) do { \ + (dst).seconds = (t1).seconds - (t2).seconds; \ + if ((t1).millis < (t2).millis) { \ + (dst).seconds--; \ + (dst).millis = (t1).millis + TEE_TIME_MILLIS_BASE - (t2).millis;\ + } else { \ + (dst).millis = (t1).millis - (t2).millis; \ + } \ + } while (0) + +/* ------------------------------------------------------------ */ +/* OTP mapping */ +/* ------------------------------------------------------------ */ +#define HW_UNIQUE_KEY_WORD1 (8) +#define HW_UNIQUE_KEY_LENGTH (16) +#define HW_UNIQUE_KEY_WORD2 (HW_UNIQUE_KEY_WORD1 + 1) +#define HW_UNIQUE_KEY_WORD3 (HW_UNIQUE_KEY_WORD1 + 2) +#define HW_UNIQUE_KEY_WORD4 (HW_UNIQUE_KEY_WORD1 + 3) + +#endif /* UTEE_DEFINES_H */ diff --git a/lib/libutee/include/utee_syscalls.h b/lib/libutee/include/utee_syscalls.h new file mode 100644 index 00000000000..50edea0b220 --- /dev/null +++ b/lib/libutee/include/utee_syscalls.h @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef UTEE_SYSCALLS_H +#define UTEE_SYSCALLS_H + +#include +#include + +#include +#include +#include + +void utee_return(uint32_t ret) /*__attribute__((noreturn))*/ ; + +void utee_log(const void *buf, size_t len); + +void utee_panic(uint32_t code) /*__attribute__((noreturn))*/ ; + +uint32_t utee_dummy(uint32_t *a); + +uint32_t utee_dummy_7args(uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, + uint32_t a5, uint32_t a6, uint32_t a7); + +uint32_t utee_nocall(void); + +TEE_Result utee_get_property(enum utee_property prop, void *buf, uint32_t len); + +TEE_Result utee_open_ta_session(const TEE_UUID *dest, + uint32_t cancel_req_to, uint32_t param_types, + TEE_Param params[4], TEE_TASessionHandle *sess, + uint32_t *ret_orig); + +TEE_Result utee_close_ta_session(TEE_TASessionHandle sess); + +TEE_Result utee_invoke_ta_command(TEE_TASessionHandle sess, + uint32_t cancel_req_to, uint32_t cmd_id, + uint32_t param_types, TEE_Param params[4], + uint32_t *ret_orig); + +TEE_Result utee_check_access_rights(uint32_t flags, const void *buf, + size_t len); + +TEE_Result utee_get_cancellation_flag(bool *cancel); + +TEE_Result utee_unmask_cancellation(bool *old_mask); + +TEE_Result utee_mask_cancellation(bool *old_mask); + +TEE_Result utee_wait(uint32_t timeout); + +TEE_Result utee_get_time(enum utee_time_category cat, TEE_Time *time); + +TEE_Result utee_set_ta_time(const TEE_Time *time); + +TEE_Result utee_cryp_state_alloc(uint32_t algo, uint32_t op_mode, + uint32_t key1, uint32_t key2, + uint32_t *state); +TEE_Result utee_cryp_state_copy(uint32_t dst, uint32_t src); +TEE_Result utee_cryp_state_free(uint32_t state); + +/* iv and iv_len are ignored for some algorithms */ +TEE_Result utee_hash_init(uint32_t state, const void *iv, size_t iv_len); +TEE_Result utee_hash_update(uint32_t state, const void *chunk, + size_t chunk_size); +TEE_Result utee_hash_final(uint32_t state, const void *chunk, + size_t chunk_size, void *hash, size_t *hash_len); + +TEE_Result utee_cipher_init(uint32_t state, const void *iv, size_t iv_len); +TEE_Result utee_cipher_update(uint32_t state, const void *src, size_t src_len, + void *dest, size_t *dest_len); +TEE_Result utee_cipher_final(uint32_t state, const void *src, size_t src_len, + void *dest, size_t *dest_len); + +/* Generic Object Functions */ +TEE_Result utee_cryp_obj_get_info(uint32_t obj, TEE_ObjectInfo *info); +TEE_Result utee_cryp_obj_restrict_usage(uint32_t obj, uint32_t usage); +TEE_Result utee_cryp_obj_get_attr(uint32_t obj, uint32_t attr_id, + void *buffer, size_t *size); + +/* Transient Object Functions */ +TEE_Result utee_cryp_obj_alloc(TEE_ObjectType type, uint32_t max_size, + uint32_t *obj); +TEE_Result utee_cryp_obj_close(uint32_t obj); +TEE_Result utee_cryp_obj_reset(uint32_t obj); +TEE_Result utee_cryp_obj_populate(uint32_t obj, TEE_Attribute *attrs, + uint32_t attr_count); +TEE_Result utee_cryp_obj_copy(uint32_t dst_obj, uint32_t src_obj); + +TEE_Result utee_cryp_obj_generate_key(uint32_t obj, uint32_t key_size, + const TEE_Attribute *params, + uint32_t param_count); + +TEE_Result utee_cryp_derive_key(uint32_t state, const TEE_Attribute *params, + uint32_t param_count, uint32_t derived_key); + +TEE_Result utee_cryp_random_number_generate(void *buf, size_t blen); + +TEE_Result utee_authenc_init(uint32_t state, const void *nonce, + size_t nonce_len, size_t tag_len, size_t aad_len, + size_t payload_len); +TEE_Result utee_authenc_update_aad(uint32_t state, const void *aad_data, + size_t aad_data_len); +TEE_Result utee_authenc_update_payload(uint32_t state, const void *src_data, + size_t src_len, void *dest_data, + size_t *dest_len); +TEE_Result utee_authenc_enc_final(uint32_t state, const void *src_data, + size_t src_len, void *dest_data, + size_t *dest_len, void *tag, + size_t *tag_len); +TEE_Result utee_authenc_dec_final(uint32_t state, const void *src_data, + size_t src_len, void *dest_data, + size_t *dest_len, const void *tag, + size_t tag_len); + +TEE_Result utee_asymm_operate(uint32_t state, const TEE_Attribute *params, + uint32_t num_params, const void *src_data, + size_t src_len, void *dest_data, + size_t *dest_len); + +TEE_Result utee_asymm_verify(uint32_t state, + const TEE_Attribute *params, uint32_t num_params, + const void *data, size_t data_len, const void *sig, + size_t sig_len); + +/* Persistant Object Functions */ +TEE_Result utee_storage_obj_open(uint32_t storage_id, void *object_id, + uint32_t object_id_len, uint32_t flags, + TEE_ObjectHandle *obj); + +TEE_Result utee_storage_obj_create(uint32_t storage_id, void *object_id, + uint32_t object_id_len, uint32_t flags, + TEE_ObjectHandle attr, const void *data, + uint32_t len, TEE_ObjectHandle *obj); + +TEE_Result utee_storage_obj_del(TEE_ObjectHandle obj); + +TEE_Result utee_storage_obj_rename(TEE_ObjectHandle obj, const void *new_obj_id, + size_t new_obj_id_len); + +/* Persistent Object Enumeration Functions */ +TEE_Result utee_storage_alloc_enum(TEE_ObjectEnumHandle *obj_enum); + +TEE_Result utee_storage_free_enum(TEE_ObjectEnumHandle obj_enum); + +TEE_Result utee_storage_reset_enum(TEE_ObjectEnumHandle obj_enum); + +TEE_Result utee_storage_start_enum(TEE_ObjectEnumHandle obj_enum, + uint32_t storage_id); + +TEE_Result utee_storage_next_enum(TEE_ObjectEnumHandle obj_enum, + TEE_ObjectInfo *info, void *obj_id, + size_t *len); + +/* Data Stream Access Functions */ +TEE_Result utee_storage_obj_read(TEE_ObjectHandle obj, void *data, size_t len, + uint32_t *count); + +TEE_Result utee_storage_obj_write(TEE_ObjectHandle obj, const void *data, + size_t len); + +TEE_Result utee_storage_obj_trunc(TEE_ObjectHandle obj, size_t len); + +TEE_Result utee_storage_obj_seek(TEE_ObjectHandle obj, int32_t offset, + TEE_Whence whence); + +#endif /* UTEE_SYSCALLS_H */ diff --git a/lib/libutee/include/utee_types.h b/lib/libutee/include/utee_types.h new file mode 100644 index 00000000000..29b081c7bde --- /dev/null +++ b/lib/libutee/include/utee_types.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef UTEE_TYPES_H +#define UTEE_TYPES_H + +enum utee_property { + UTEE_PROP_TEE_API_VERSION = 0, + UTEE_PROP_TEE_DESCR, + UTEE_PROP_TEE_DEV_ID, + UTEE_PROP_TEE_SYS_TIME_PROT_LEVEL, + UTEE_PROP_TEE_TA_TIME_PROT_LEVEL, + UTEE_PROP_TEE_ARITH_MAX_BIG_INT_SIZE, + UTEE_PROP_CLIENT_ID, + UTEE_PROP_TA_APP_ID, +}; + +enum utee_time_category { + UTEE_TIME_CAT_SYSTEM = 0, + UTEE_TIME_CAT_TA_PERSISTENT, + UTEE_TIME_CAT_REE +}; + +#endif /* UTEE_TYPES_H */ diff --git a/lib/libutee/sub.mk b/lib/libutee/sub.mk new file mode 100644 index 00000000000..6d136437898 --- /dev/null +++ b/lib/libutee/sub.mk @@ -0,0 +1,25 @@ +global-incdirs-y += include + +srcs-y += tee_api_property.c +cflags-tee_api_property.c-y += -Wno-redundant-decls + +srcs-y += tee_user_mem.c +cflags-remove-tee_user_mem.c-y += -Wdeclaration-after-statement + +srcs-y += abort.c +cflags-abort.c-y += -Wno-missing-prototypes -Wno-missing-declarations +cflags-abort.c-y += -Wno-error + +srcs-y += ta_trace.c +cflags-ta_trace.c-y += -Wno-redundant-decls + +srcs-y += assert.c +cflags-assert.c-y += -Wno-missing-prototypes -Wno-missing-declarations + +srcs-y += base64.c +srcs-y += tee_api_arith.c +srcs-y += tee_api.c +srcs-y += tee_api_objects.c +srcs-y += tee_api_operations.c + +subdirs-y += arch/$(ARCH) diff --git a/lib/libutee/ta_trace.c b/lib/libutee/ta_trace.c new file mode 100644 index 00000000000..8e90a4b2028 --- /dev/null +++ b/lib/libutee/ta_trace.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#if (CFG_TEE_TA_LOG_LEVEL > 0) +#include +#include +#include + +#include +#include +#include +#include "utee_misc.h" + +/*****************************************************************************/ + +static const char *const trace_level_strings[] = { + "NONE", "ALW", "ERR", "INF", "DBG", "FLW" +}; + +static const char failed[] = "uta trace failed"; + +/*****************************************************************************/ + +/* Format trace of user ta. Inline with kernel ta */ +static int format_trace(const char *function, int line, int level, + const char *prefix, const char *in, char *out) +{ + const char *func; + int nb_char = MAX_PRINT_SIZE; + + if (function) { +#ifdef TRACE_FUNC_LENGTH_CST + char func_buf[MAX_FUNC_PRINT_SIZE]; + int flen = strlen(function); + + /* Limit the function name to MAX_FUNC_PRINT_SIZE characters. */ + strncpy(func_buf, function, flen > MAX_FUNC_PRINT_SIZE ? + (MAX_FUNC_PRINT_SIZE - 1) : flen); + if (flen < (MAX_FUNC_PRINT_SIZE - 1)) { + memset(func_buf + flen, 0x20, + (MAX_FUNC_PRINT_SIZE - flen)); + } + func_buf[MAX_FUNC_PRINT_SIZE - 1] = '\0'; + func = func_buf; +#else + func = function; +#endif + nb_char = + snprintf(out, MAX_PRINT_SIZE, "%s [%p] %s:%s:%d: %s\n", + trace_level_strings[level], + (void *)utee_get_ta_exec_id(), prefix, func, line, + in); + } else { + /* copy buffer and insure '\n' terminated, before '\0' */ + memcpy(out, in, MAX_PRINT_SIZE); + *(out + MAX_PRINT_SIZE - 1) = '\0'; + nb_char = strlen(out); + if (nb_char == (MAX_PRINT_SIZE - 2)) { + *(out + (MAX_PRINT_SIZE - 2)) = '\n'; + } else if (*(out + nb_char - 1) != '\n') { + *(out + nb_char) = '\n'; + *(out + nb_char + 1) = '\0'; + } + } + return nb_char; +} + +/* To be call from user side */ +int _dprintf_uta(const char *function, int line, int level, const char *prefix, + const char *fmt, ...) +{ + char to_format[MAX_PRINT_SIZE]; + char formatted[MAX_PRINT_SIZE]; + char trunc[] = "...\n"; + va_list ap; + int s; + + va_start(ap, fmt); + s = vsnprintf(to_format, sizeof(to_format), fmt, ap); + va_end(ap); + + if (s < 0) { + utee_log(failed, strlen(failed) + 1); + return s; + } + if (((unsigned int)s >= sizeof(to_format)) && + (MAX_PRINT_SIZE > sizeof(trunc))) + memcpy(&to_format[sizeof(to_format) - sizeof(trunc)], trunc, + sizeof(trunc)); + + /* Format trace at user side */ + s = format_trace(function, line, level, prefix, to_format, formatted); + + /* sys call */ + utee_log(formatted, strlen(formatted) + 1); + + return s; +} + +/* + * printf and puts - stdio printf support + * + * 'printf()' and 'puts()' traces have the 'info' trace level. + * Traces are prefixed with string "[ta log] ". + */ +int printf(const char *fmt, ...) +{ + char to_format[MAX_PRINT_SIZE]; + char prefix[] = "[ta log] "; + char trunc[] = "...\n"; + va_list ap; + int s; + + if (tahead_get_trace_level() <= TRACE_PRINTF_LEVEL) + return 0; + + s = snprintf(to_format, sizeof(to_format), "%s", prefix); + if (s < 0) { + utee_log(failed, strlen(failed) + 1); + return s; + } + if ((unsigned int)s >= sizeof(to_format)) { + utee_log(failed, strlen(failed) + 1); + return 0; + } + + va_start(ap, fmt); + s = vsnprintf(to_format + s, sizeof(to_format) - s, fmt, ap); + va_end(ap); + + if (s < 0) { + utee_log(failed, strlen(failed) + 1); + return s; + } + if (((unsigned int)s >= (sizeof(to_format) - strlen(prefix)))) { + memcpy(&to_format[sizeof(to_format) - sizeof(trunc)], trunc, + sizeof(trunc)); + s = sizeof(to_format) - sizeof(prefix) - sizeof(trunc); + } + + /* sys call */ + utee_log(to_format, strlen(to_format) + 1); + + return s; +} + +int puts(const char *str) +{ + return printf("%s", str); +} + +#else /* CFG_TEE_TA_LOG_LEVEL */ +#include +int printf(const char *fmt, ...) +{ + return 0; +} + +int puts(const char *str) +{ + return 0; +} +#endif /* CFG_TEE_TA_LOG_LEVEL */ diff --git a/lib/libutee/tee_api.c b/lib/libutee/tee_api.c new file mode 100644 index 00000000000..af645474ac5 --- /dev/null +++ b/lib/libutee/tee_api.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include + +#include +#include +#include +#include "tee_user_mem.h" + +static void *tee_api_instance_data; + +/* System API - Misc */ + +void TEE_Panic(TEE_Result panicCode) +{ + utee_panic(panicCode); +} + +/* System API - Internal Client API */ + +TEE_Result TEE_OpenTASession(const TEE_UUID *destination, + uint32_t cancellationRequestTimeout, + uint32_t paramTypes, TEE_Param params[4], + TEE_TASessionHandle *session, + uint32_t *returnOrigin) +{ + TEE_Result res; + + res = utee_open_ta_session(destination, cancellationRequestTimeout, + paramTypes, params, session, returnOrigin); + /* + * Specification says that *session must hold TEE_HANDLE_NULL is + * TEE_SUCCESS isn't returned. Set it here explicitly in case + * the syscall fails before out parameters has been updated. + */ + if (res != TEE_SUCCESS) + *session = TEE_HANDLE_NULL; + + return res; +} + +void TEE_CloseTASession(TEE_TASessionHandle session) +{ + if (session != TEE_HANDLE_NULL) { + TEE_Result res = utee_close_ta_session(session); + if (res != TEE_SUCCESS) + TEE_Panic(res); + } +} + +TEE_Result TEE_InvokeTACommand(TEE_TASessionHandle session, + uint32_t cancellationRequestTimeout, + uint32_t commandID, uint32_t paramTypes, + TEE_Param params[4], uint32_t *returnOrigin) +{ + return utee_invoke_ta_command(session, cancellationRequestTimeout, + commandID, paramTypes, params, + returnOrigin); +} + +/* System API - Cancellations */ + +bool TEE_GetCancellationFlag(void) +{ + bool c; + TEE_Result res = utee_get_cancellation_flag(&c); + + if (res != TEE_SUCCESS) + TEE_Panic(res); + return c; +} + +bool TEE_UnmaskCancellation(void) +{ + bool old_mask; + TEE_Result res = utee_unmask_cancellation(&old_mask); + + if (res != TEE_SUCCESS) + TEE_Panic(res); + return old_mask; +} + +bool TEE_MaskCancellation(void) +{ + bool old_mask; + TEE_Result res = utee_mask_cancellation(&old_mask); + + if (res != TEE_SUCCESS) + TEE_Panic(res); + return old_mask; +} + +/* System API - Memory Management */ + +TEE_Result TEE_CheckMemoryAccessRights(uint32_t accessFlags, void *buffer, + size_t size) +{ + TEE_Result res; + + if (size == 0) + return TEE_SUCCESS; + + /* Check access rights against memory mapping */ + res = utee_check_access_rights(accessFlags, buffer, size); + if (res != TEE_SUCCESS) + goto out; + + /* + * Check access rights against input parameters + * Previous legacy code was removed and will need to be restored + */ + + res = TEE_SUCCESS; +out: + return res; +} + +void TEE_SetInstanceData(void *instanceData) +{ + tee_api_instance_data = instanceData; +} + +void *TEE_GetInstanceData(void) +{ + return tee_api_instance_data; +} + +void *TEE_MemMove(void *dest, const void *src, uint32_t size) +{ + return memmove(dest, src, size); +} + +int32_t TEE_MemCompare(const void *buffer1, const void *buffer2, uint32_t size) +{ + return memcmp(buffer1, buffer2, size); +} + +void *TEE_MemFill(void *buff, uint32_t x, uint32_t size) +{ + return memset(buff, x, size); +} + +/* Date & Time API */ + +void TEE_GetSystemTime(TEE_Time *time) +{ + TEE_Result res = utee_get_time(UTEE_TIME_CAT_SYSTEM, time); + + if (res != TEE_SUCCESS) + TEE_Panic(0); +} + +TEE_Result TEE_Wait(uint32_t timeout) +{ + TEE_Result res = utee_wait(timeout); + + if (res != TEE_SUCCESS && res != TEE_ERROR_CANCEL) + TEE_Panic(res); + + return res; +} + +TEE_Result TEE_GetTAPersistentTime(TEE_Time *time) +{ + return utee_get_time(UTEE_TIME_CAT_TA_PERSISTENT, time); +} + +TEE_Result TEE_SetTAPersistentTime(const TEE_Time *time) +{ + return utee_set_ta_time(time); +} + +void TEE_GetREETime(TEE_Time *time) +{ + TEE_Result res = utee_get_time(UTEE_TIME_CAT_REE, time); + + if (res != TEE_SUCCESS) + TEE_Panic(0); +} + +void *TEE_Malloc(size_t len, uint32_t hint) +{ + return tee_user_mem_alloc(len, hint); +} + +void *TEE_Realloc(void *buffer, uint32_t newSize) +{ + /* + * GP TEE Internal API specifies newSize as 'uint32_t'. + * use unsigned 'size_t' type. it is at least 32bit! + */ + return tee_user_mem_realloc(buffer, (size_t) newSize); +} + +void TEE_Free(void *buffer) +{ + tee_user_mem_free(buffer); +} diff --git a/lib/libutee/tee_api_arith.c b/lib/libutee/tee_api_arith.c new file mode 100644 index 00000000000..7f49ac374f5 --- /dev/null +++ b/lib/libutee/tee_api_arith.c @@ -0,0 +1,581 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include + +/* + * The mem pool. + * We have a pool of scratch memory for internal usage. + * The variables in the pool are twice the size of the max allowed + * size from the TA. This is to coop with modulare multiplication. + */ + +#define MPA_INTERNAL_MEM_POOL_SIZE 12 + +/* + * THIS IS THE MAXIMUM NUMBER OF BITS THAT THE LIBRARY SUPPORTS. + * It defines the size of the scratch memory pool for the underlying + * mpa library. + */ +#define TEE_MAX_NUMBER_OF_SUPPORTED_BITS 2048 + +static uint32_t mempool_u32[mpa_scratch_mem_size_in_U32( + MPA_INTERNAL_MEM_POOL_SIZE, + TEE_MAX_NUMBER_OF_SUPPORTED_BITS)]; +static mpa_scratch_mem mempool = (mpa_scratch_mem)&mempool_u32; + +/************************************************************* + * PANIC + *************************************************************/ + +/* + * TEE_BigInt_Panic + * + * This is a temporary solution for testing the TEE_BigInt lib + */ +static void __attribute__ ((noreturn)) TEE_BigInt_Panic(const char *msg) +{ + printf("PANIC: %s\n", msg); + TEE_Panic(0xB16127 /*BIGINT*/); + while (1) + ; /* Panic will crash the thread */ +} + +/************************************************************* + * INITIALIZATION FUNCTIONS + *************************************************************/ + +/* + * TEE_MathAPI_Init + */ +void TEE_MathAPI_Init(void) +{ + mpa_init_scratch_mem(mempool, MPA_INTERNAL_MEM_POOL_SIZE, + TEE_MAX_NUMBER_OF_SUPPORTED_BITS); +#ifdef DEBUG + printf("TEE Math Lib configured to max %d bit integers.\n", + TEE_MAX_NUMBER_OF_SUPPORTED_BITS); + printf("Using %d bytes for each variable.\n", + mpa_StaticVarSizeInU32(TEE_MAX_NUMBER_OF_SUPPORTED_BITS)); + printf("Using %d bytes for each temporary variable.\n", + mpa_StaticTempVarSizeInU32(TEE_MAX_NUMBER_OF_SUPPORTED_BITS)); + printf("Using %d temporary variables.\n", MPA_INTERNAL_MEM_POOL_SIZE); + printf("Total scratch memory is %lu bytes.\n", + (unsigned long)mpa_scratch_memsize_in_U32( + MPA_INTERNAL_MEM_POOL_SIZE, + TEE_MAX_NUMBER_OF_SUPPORTED_BITS)); +#endif +} + +/* + * TEE_BigIntInit + */ +void TEE_BigIntInit(TEE_BigInt *bigInt, size_t len) +{ + mpa_init_static((mpa_num_base *)bigInt, (uint32_t)len); +} + +/* + * TEE_BigIntInitFMM + */ +void TEE_BigIntInitFMM(const TEE_BigIntFMM *bigIntFMM, size_t len) +{ + mpanum op = (mpa_num_base *)bigIntFMM; + + op->alloc = U32_TO_ASIZE(len - MPA_NUMBASE_METADATA_SIZE_IN_U32); + op->size = 0; +} + +/* + * TEE_BigIntInitFMMContext + */ +void TEE_BigIntInitFMMContext(TEE_BigIntFMMContext *context, + size_t len, const TEE_BigInt *modulus) +{ + mpa_fmm_context mpa_context = (mpa_fmm_context_base *)context; + mpanum mpa_modulus = (mpa_num_base *)modulus; + + mpa_init_static_fmm_context(mpa_context, (uint32_t)len); + mpa_compute_fmm_context(mpa_modulus, mpa_context->r_ptr, + mpa_context->r2_ptr, &mpa_context->n_inv, + mempool); +} + +/************************************************************* + * MEMORY ALLOCATION AND SIZE + *************************************************************/ + +/* + * TEE_BigIntFMMSizeInU32 + */ +size_t TEE_BigIntFMMSizeInU32(size_t modulusSizeInBits) +{ + return TEE_BigIntSizeInU32(modulusSizeInBits) + 1; +} + +/* + * TEE_BigIntFMMContextSizeInU32 + */ +size_t TEE_BigIntFMMContextSizeInU32(size_t modulusSizeInBits) +{ + return mpa_fmm_context_size_in_U32(modulusSizeInBits); +} + +/************************************************************* + * CONVERSION FUNCTIONS + *************************************************************/ + +/* + * TEE_BigIntConvertFromOctetString + */ +TEE_Result TEE_BigIntConvertFromOctetString(TEE_BigInt *dest, + const uint8_t *buffer, + size_t bufferLen, + int32_t sign) +{ + mpanum mpa_dest = (mpa_num_base *)dest; + bool negative = sign < 0; + + if (mpa_set_oct_str(mpa_dest, buffer, bufferLen, negative) != 0) + return TEE_ERROR_OVERFLOW; + + return TEE_SUCCESS; +} + +/* + * TEE_BigIntConvertToOctetString + */ +TEE_Result TEE_BigIntConvertToOctetString(uint8_t *buffer, + size_t *bufferLen, + const TEE_BigInt *bigInt) +{ + mpanum n = (mpa_num_base *)bigInt; + + if (mpa_get_oct_str(buffer, bufferLen, n) != 0) + return TEE_ERROR_SHORT_BUFFER; + return TEE_SUCCESS; +} + +/* + * TEE_BigIntConvertFromS32 + */ +void TEE_BigIntConvertFromS32(TEE_BigInt *dest, int32_t shortVal) +{ + mpanum mpa_dest = (mpa_num_base *)dest; + +#if (MPA_WORD_SIZE == 32) + mpa_set_S32(mpa_dest, shortVal); +#else +#error "Write code for digit size != 32" +#endif +} + +/* + * TEE_BigIntConvertToS32 + */ +TEE_Result TEE_BigIntConvertToS32(int32_t *dest, const TEE_BigInt *src) +{ + mpanum mpa_src = (mpa_num_base *)src; + + if (mpa_get_S32(dest, mpa_src) == 0) + return TEE_SUCCESS; + else + return TEE_ERROR_OVERFLOW; +} + +/************************************************************* + * LOGICAL OPERATIONS + *************************************************************/ + +/* + * TEE_BigIntCmp + */ +int32_t TEE_BigIntCmp(const TEE_BigInt *op1, const TEE_BigInt *op2) +{ + mpanum mpa_op1 = (mpa_num_base *)op1; + mpanum mpa_op2 = (mpa_num_base *)op2; + + return mpa_cmp(mpa_op1, mpa_op2); +} + +/* + * TEE_BigIntCmpS32 + */ +int32_t TEE_BigIntCmpS32(const TEE_BigInt *op, int32_t shortVal) +{ + mpanum mpa_op = (mpa_num_base *)op; + + return mpa_cmp_short(mpa_op, shortVal); +} + +/* + * TEE_BigIntShiftRight + */ +void TEE_BigIntShiftRight(TEE_BigInt *dest, const TEE_BigInt *op, + size_t bits) +{ + mpanum mpa_dest = (mpa_num_base *)dest; + mpanum mpa_op = (mpa_num_base *)op; + + mpa_shift_right(mpa_dest, mpa_op, (mpa_asize_t) bits); +} + +/* + * TEE_BigIntGetBit + */ +bool TEE_BigIntGetBit(const TEE_BigInt *src, uint32_t bitIndex) +{ + mpanum mpa_src = (mpa_num_base *)src; + + return mpa_get_bit(mpa_src, bitIndex); +} + +/* + * TEE_BigIntGetBitCount + */ +uint32_t TEE_BigIntGetBitCount(const TEE_BigInt *src) +{ + mpanum mpa_src = (mpa_num_base *)src; + + return mpa_highest_bit_index(mpa_src) + 1; +} + +/************************************************************* + * BASIC ARITHMETIC OPERATIONS + *************************************************************/ + +/* + * TEE_BigIntAdd + */ +void TEE_BigIntAdd(TEE_BigInt *dest, const TEE_BigInt *op1, + const TEE_BigInt *op2) +{ + mpanum mpa_dest = (mpa_num_base *)dest; + mpanum mpa_op1 = (mpa_num_base *)op1; + mpanum mpa_op2 = (mpa_num_base *)op2; + + mpa_add(mpa_dest, mpa_op1, mpa_op2, mempool); +} + +/* + * TEE_BigIntSub + */ +void TEE_BigIntSub(TEE_BigInt *dest, const TEE_BigInt *op1, + const TEE_BigInt *op2) +{ + mpanum mpa_dest = (mpa_num_base *)dest; + mpanum mpa_op1 = (mpa_num_base *)op1; + mpanum mpa_op2 = (mpa_num_base *)op2; + + mpa_sub(mpa_dest, mpa_op1, mpa_op2, mempool); +} + +/* + * TEE_BigIntNeg + */ +void TEE_BigIntNeg(TEE_BigInt *dest, const TEE_BigInt *src) +{ + mpanum mpa_dest = (mpa_num_base *)dest; + mpanum mpa_src = (mpa_num_base *)src; + + mpa_neg(mpa_dest, mpa_src); +} + +/* + * TEE_BigIntMul + */ +void TEE_BigIntMul(TEE_BigInt *dest, const TEE_BigInt *op1, + const TEE_BigInt *op2) +{ + mpanum mpa_dest = (mpa_num_base *)dest; + mpanum mpa_op1 = (mpa_num_base *)op1; + mpanum mpa_op2 = (mpa_num_base *)op2; + + mpa_mul(mpa_dest, mpa_op1, mpa_op2, mempool); +} + +/* + * TEE_BigIntSquare + */ +void TEE_BigIntSquare(TEE_BigInt *dest, const TEE_BigInt *op) +{ + mpanum mpa_dest = (mpa_num_base *)dest; + mpanum mpa_op = (mpa_num_base *)op; + + mpa_mul(mpa_dest, mpa_op, mpa_op, mempool); +} + +/* + * TEE_BigIntDiv + */ +void TEE_BigIntDiv(TEE_BigInt *dest_q, TEE_BigInt *dest_r, + const TEE_BigInt *op1, const TEE_BigInt *op2) +{ + mpanum mpa_dest_q = (mpa_num_base *)dest_q; + mpanum mpa_dest_r = (mpa_num_base *)dest_r; + mpanum mpa_op1 = (mpa_num_base *)op1; + mpanum mpa_op2 = (mpa_num_base *)op2; + + if (TEE_BigIntCmpS32(op2, 0) == 0) + TEE_BigInt_Panic("Divisor is zero"); + + mpa_div(mpa_dest_q, mpa_dest_r, mpa_op1, mpa_op2, mempool); +} + +/************************************************************* + * MODULUS OPERATIONS + *************************************************************/ + +/* + * TEE_BigIntMod + */ +void TEE_BigIntMod(TEE_BigInt *dest, const TEE_BigInt *op, + const TEE_BigInt *n) +{ + mpanum mpa_dest = (mpa_num_base *)dest; + mpanum mpa_op = (mpa_num_base *)op; + mpanum mpa_n = (mpa_num_base *)n; + + if (TEE_BigIntCmpS32(n, 2) < 0) + TEE_BigInt_Panic("Modulus is too short"); + + mpa_mod(mpa_dest, mpa_op, mpa_n, mempool); + + if (mpa_cmp_short(mpa_dest, 0) < 0) + mpa_add(mpa_dest, mpa_dest, mpa_n, mempool); +} + +/* + * TEE_BigIntAddMod + */ +void TEE_BigIntAddMod(TEE_BigInt *dest, const TEE_BigInt *op1, + const TEE_BigInt *op2, const TEE_BigInt *n) +{ + mpanum mpa_dest = (mpa_num_base *)dest; + mpanum mpa_op1 = (mpa_num_base *)op1; + mpanum mpa_op2 = (mpa_num_base *)op2; + mpanum mpa_n = (mpa_num_base *)n; + + if (TEE_BigIntCmpS32(n, 2) < 0) + TEE_BigInt_Panic("Modulus is too short"); + + mpa_add_mod(mpa_dest, mpa_op1, mpa_op2, mpa_n, mempool); + if (mpa_cmp_short(mpa_dest, 0) < 0) + mpa_add(mpa_dest, mpa_dest, mpa_n, mempool); +} + +/* + * TEE_BigIntSubMod + */ +void TEE_BigIntSubMod(TEE_BigInt *dest, const TEE_BigInt *op1, + const TEE_BigInt *op2, const TEE_BigInt *n) +{ + mpanum mpa_dest = (mpa_num_base *)dest; + mpanum mpa_op1 = (mpa_num_base *)op1; + mpanum mpa_op2 = (mpa_num_base *)op2; + mpanum mpa_n = (mpa_num_base *)n; + + if (TEE_BigIntCmpS32(n, 2) < 0) + TEE_BigInt_Panic("Modulus is too short"); + + mpa_sub_mod(mpa_dest, mpa_op1, mpa_op2, mpa_n, mempool); + if (mpa_cmp_short(mpa_dest, 0) < 0) + mpa_add(mpa_dest, mpa_dest, mpa_n, mempool); +} + +/* + * TEE_BigIntMulMod + */ +void TEE_BigIntMulMod(TEE_BigInt *dest, const TEE_BigInt *op1, + const TEE_BigInt *op2, const TEE_BigInt *n) +{ + mpanum mpa_dest = (mpa_num_base *)dest; + mpanum mpa_op1 = (mpa_num_base *)op1; + mpanum mpa_op2 = (mpa_num_base *)op2; + mpanum mpa_n = (mpa_num_base *)n; + + if (TEE_BigIntCmpS32(n, 2) < 0) + TEE_BigInt_Panic("Modulus is too short"); + + mpa_mul_mod(mpa_dest, mpa_op1, mpa_op2, mpa_n, mempool); + if (mpa_cmp_short(mpa_dest, 0) < 0) + mpa_add(mpa_dest, mpa_dest, mpa_n, mempool); +} + +/* + * TEE_BigIntSquareMod + */ +void TEE_BigIntSquareMod(TEE_BigInt *dest, const TEE_BigInt *op, + const TEE_BigInt *n) +{ + TEE_BigIntMulMod(dest, op, op, n); +} + +/* + * TEE_BigIntInvMod + */ +void TEE_BigIntInvMod(TEE_BigInt *dest, const TEE_BigInt *op, + const TEE_BigInt *n) +{ + mpanum mpa_dest = (mpa_num_base *)dest; + mpanum mpa_op = (mpa_num_base *)op; + mpanum mpa_n = (mpa_num_base *)n; + + if (TEE_BigIntCmpS32(n, 2) < 0 || TEE_BigIntCmpS32(op, 0) == 0) + TEE_BigInt_Panic("too small modulus or trying to invert zero"); + + mpa_inv_mod(mpa_dest, mpa_op, mpa_n, mempool); +} + +/************************************************************* + * OTHER ARITHMETIC OPERATIONS + *************************************************************/ + +/* + * TEE_BigIntRelativePrime + */ +bool TEE_BigIntRelativePrime(const TEE_BigInt *op1, const TEE_BigInt *op2) +{ + mpanum mpa_op1 = (mpa_num_base *)op1; + mpanum mpa_op2 = (mpa_num_base *)op2; + mpanum gcd; + uint32_t cmp; + + mpa_alloc_static_temp_var(&gcd, mempool); + + mpa_gcd(gcd, mpa_op1, mpa_op2, mempool); + cmp = mpa_cmp_short(gcd, 1); + + mpa_free_static_temp_var(&gcd, mempool); + + return cmp == 0 ? true : false; +} + +/* + * TEE_BigIntExtendedGcd + */ +void TEE_BigIntComputeExtendedGcd(TEE_BigInt *gcd, TEE_BigInt *u, + TEE_BigInt *v, const TEE_BigInt *op1, + const TEE_BigInt *op2) +{ + mpanum mpa_gcd_res = (mpa_num_base *)gcd; + mpanum mpa_u = (mpa_num_base *)u; + mpanum mpa_v = (mpa_num_base *)v; + mpanum mpa_op1 = (mpa_num_base *)op1; + mpanum mpa_op2 = (mpa_num_base *)op2; + + mpa_extended_gcd(mpa_gcd_res, mpa_u, mpa_v, mpa_op1, mpa_op2, mempool); +} + +/* + * TEE_BigIntIsProbablePrime + */ +int32_t TEE_BigIntIsProbablePrime(const TEE_BigInt *op, + uint32_t confidenceLevel) +{ + mpanum mpa_op = (mpa_num_base *)op; + + if (confidenceLevel < 80) + confidenceLevel = 80; + + if (confidenceLevel > 256) + confidenceLevel = 256; + + return mpa_is_prob_prime(mpa_op, confidenceLevel, mempool); +} + +/************************************************************* + * FAST MODULAR MULTIPLICATION + *************************************************************/ + +/* + * TEE_BigIntConvertToFMM + */ +void TEE_BigIntConvertToFMM(TEE_BigIntFMM *dest, + const TEE_BigInt *src, + const TEE_BigInt *n, + const TEE_BigIntFMMContext *context) +{ + mpanum mpa_dest = (mpa_num_base *)dest; + mpanum mpa_op1 = (mpa_num_base *)src; + mpanum mpa_n = (mpa_num_base *)n; + mpa_fmm_context mpa_context = (mpa_fmm_context_base *)context; + + /* calculate dest = Mont(src, r2) */ + mpa_montgomery_mul(mpa_dest, mpa_op1, mpa_context->r2_ptr, mpa_n, + mpa_context->n_inv, mempool); +} + +/* + * TEE_BigIntConvertFromFMM + */ +void TEE_BigIntConvertFromFMM(TEE_BigInt *dest, + const TEE_BigIntFMM *src, + const TEE_BigInt *n, + const TEE_BigIntFMMContext *context) +{ + mpanum mpa_dest = (mpa_num_base *)dest; + mpanum mpa_op2 = (mpa_num_base *)src; + mpanum mpa_n = (mpa_num_base *)n; + mpa_fmm_context mpa_context = (mpa_fmm_context_base *)context; + mpanum temp_dest; + + /* + * Since dest in BigIntFFMCompute (i.e. dest in mpa_montgomery_mul) + * must have alloc one word more than the size of n, we must + * use a temp variable during the conversion. + */ + mpa_alloc_static_temp_var(&temp_dest, mempool); + + /* calculate dest = Mont(1,src) */ + mpa_montgomery_mul(temp_dest, mpa_constant_one(), mpa_op2, mpa_n, + mpa_context->n_inv, mempool); + + mpa_copy(mpa_dest, temp_dest); + mpa_free_static_temp_var(&temp_dest, mempool); +} + +/* + * TEE_BigIntComputeFMM + */ +void TEE_BigIntComputeFMM(TEE_BigIntFMM *dest, + const TEE_BigIntFMM *op1, + const TEE_BigIntFMM *op2, + const TEE_BigInt *n, + const TEE_BigIntFMMContext *context) +{ + mpanum mpa_dest = (mpa_num_base *)dest; + mpanum mpa_op1 = (mpa_num_base *)op1; + mpanum mpa_op2 = (mpa_num_base *)op2; + mpanum mpa_n = (mpa_num_base *)n; + mpa_fmm_context mpa_context = (mpa_fmm_context_base *)context; + + mpa_montgomery_mul(mpa_dest, mpa_op1, mpa_op2, mpa_n, + mpa_context->n_inv, mempool); +} diff --git a/lib/libutee/tee_api_objects.c b/lib/libutee/tee_api_objects.c new file mode 100644 index 00000000000..2447406b280 --- /dev/null +++ b/lib/libutee/tee_api_objects.c @@ -0,0 +1,529 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include + +#include +#include + +#include + +#define TEE_USAGE_DEFAULT 0xffffffff + +#define TEE_ATTR_BIT_VALUE (1 << 29) +#define TEE_ATTR_BIT_PROTECTED (1 << 28) + +/* Data and Key Storage API - Generic Object Functions */ +void TEE_GetObjectInfo(TEE_ObjectHandle object, TEE_ObjectInfo *objectInfo) +{ + TEE_Result res; + + res = utee_cryp_obj_get_info((uint32_t)object, objectInfo); + if (res != TEE_SUCCESS) + TEE_Panic(res); +} + +void TEE_RestrictObjectUsage(TEE_ObjectHandle object, uint32_t objectUsage) +{ + TEE_Result res; + res = utee_cryp_obj_restrict_usage((uint32_t)object, objectUsage); + + if (res != TEE_SUCCESS) + TEE_Panic(0); +} + +TEE_Result TEE_GetObjectBufferAttribute(TEE_ObjectHandle object, + uint32_t attributeID, void *buffer, + size_t *size) +{ + TEE_Result res; + TEE_ObjectInfo info; + + res = utee_cryp_obj_get_info((uint32_t)object, &info); + if (res != TEE_SUCCESS) + TEE_Panic(0); + + if ((info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) + TEE_Panic(0); + + /* This function only supports reference attributes */ + if ((attributeID & TEE_ATTR_BIT_VALUE) != 0) + TEE_Panic(0); + + res = + utee_cryp_obj_get_attr((uint32_t)object, attributeID, buffer, + size); + + if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND && + res != TEE_ERROR_SHORT_BUFFER) + TEE_Panic(0); + + return res; +} + +TEE_Result TEE_GetObjectValueAttribute(TEE_ObjectHandle object, + uint32_t attributeID, uint32_t *a, + uint32_t *b) +{ + TEE_Result res; + TEE_ObjectInfo info; + uint32_t buf[2]; + size_t size = sizeof(buf); + + res = utee_cryp_obj_get_info((uint32_t)object, &info); + if (res != TEE_SUCCESS) + TEE_Panic(0); + + if ((info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) + TEE_Panic(0); + + /* This function only supports value attributes */ + if ((attributeID & TEE_ATTR_BIT_VALUE) == 0) + TEE_Panic(0); + + res = + utee_cryp_obj_get_attr((uint32_t)object, attributeID, buf, &size); + + if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND && + res != TEE_ERROR_ACCESS_DENIED) + TEE_Panic(0); + + if (size != sizeof(buf)) + TEE_Panic(0); + + *a = buf[0]; + *b = buf[1]; + + return res; +} + +void TEE_CloseObject(TEE_ObjectHandle object) +{ + TEE_Result res; + + if (object == TEE_HANDLE_NULL) + return; + + res = utee_cryp_obj_close((uint32_t)object); + if (res != TEE_SUCCESS) + TEE_Panic(0); +} + +/* Data and Key Storage API - Transient Object Functions */ + +TEE_Result TEE_AllocateTransientObject(TEE_ObjectType objectType, + uint32_t maxObjectSize, + TEE_ObjectHandle *object) +{ + TEE_Result res; + uint32_t obj; + + res = utee_cryp_obj_alloc(objectType, maxObjectSize, &obj); + if (res == TEE_SUCCESS) + *object = (TEE_ObjectHandle) obj; + return res; +} + +void TEE_FreeTransientObject(TEE_ObjectHandle object) +{ + TEE_Result res; + TEE_ObjectInfo info; + + if (object == TEE_HANDLE_NULL) + return; + + res = utee_cryp_obj_get_info((uint32_t)object, &info); + if (res != TEE_SUCCESS) + TEE_Panic(0); + + if ((info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) != 0) + TEE_Panic(0); + + res = utee_cryp_obj_close((uint32_t)object); + if (res != TEE_SUCCESS) + TEE_Panic(0); +} + +void TEE_ResetTransientObject(TEE_ObjectHandle object) +{ + TEE_Result res; + TEE_ObjectInfo info; + + if (object == TEE_HANDLE_NULL) + return; + + res = utee_cryp_obj_get_info((uint32_t)object, &info); + if (res != TEE_SUCCESS) + TEE_Panic(0); + + if ((info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) != 0) + TEE_Panic(0); + + res = utee_cryp_obj_reset((uint32_t)object); + if (res != TEE_SUCCESS) + TEE_Panic(0); +} + +TEE_Result TEE_PopulateTransientObject(TEE_ObjectHandle object, + TEE_Attribute *attrs, + uint32_t attrCount) +{ + TEE_Result res; + TEE_ObjectInfo info; + + res = utee_cryp_obj_get_info((uint32_t)object, &info); + if (res != TEE_SUCCESS) + TEE_Panic(0); + + /* Must be a transient object */ + if ((info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) != 0) + TEE_Panic(0); + + /* Must not be initialized already */ + if ((info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) != 0) + TEE_Panic(0); + + res = utee_cryp_obj_populate((uint32_t)object, attrs, attrCount); + if (res != TEE_SUCCESS && res != TEE_ERROR_BAD_PARAMETERS) + TEE_Panic(res); + return res; +} + +void TEE_InitRefAttribute(TEE_Attribute *attr, uint32_t attributeID, + void *buffer, size_t length) +{ + if (attr == NULL) + TEE_Panic(0); + if ((attributeID & TEE_ATTR_BIT_VALUE) != 0) + TEE_Panic(0); + attr->attributeID = attributeID; + attr->content.ref.buffer = buffer; + attr->content.ref.length = length; +} + +void TEE_InitValueAttribute(TEE_Attribute *attr, uint32_t attributeID, + uint32_t a, uint32_t b) +{ + if (attr == NULL) + TEE_Panic(0); + if ((attributeID & TEE_ATTR_BIT_VALUE) == 0) + TEE_Panic(0); + attr->attributeID = attributeID; + attr->content.value.a = a; + attr->content.value.b = b; +} + +void TEE_CopyObjectAttributes(TEE_ObjectHandle destObject, + TEE_ObjectHandle srcObject) +{ + TEE_Result res; + TEE_ObjectInfo dst_info; + TEE_ObjectInfo src_info; + + res = utee_cryp_obj_get_info((uint32_t)destObject, &dst_info); + if (res != TEE_SUCCESS) + TEE_Panic(0); + + res = utee_cryp_obj_get_info((uint32_t)srcObject, &src_info); + if (res != TEE_SUCCESS) + TEE_Panic(0); + + if ((src_info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) + TEE_Panic(0); + if ((dst_info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) != 0) + TEE_Panic(0); + if ((dst_info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) != 0) + TEE_Panic(0); + + res = utee_cryp_obj_copy((uint32_t)destObject, (uint32_t)srcObject); + if (res != TEE_SUCCESS) + TEE_Panic(0); +} + +TEE_Result TEE_GenerateKey(TEE_ObjectHandle object, uint32_t keySize, + TEE_Attribute *params, uint32_t paramCount) +{ + TEE_Result res; + + res = utee_cryp_obj_generate_key((uint32_t)object, keySize, + params, paramCount); + + if (res != TEE_SUCCESS) + TEE_Panic(0); + + return res; +} + +/* Data and Key Storage API - Persistent Object Functions */ + +TEE_Result TEE_OpenPersistentObject(uint32_t storageID, void *objectID, + size_t objectIDLen, uint32_t flags, + TEE_ObjectHandle *object) +{ + if (storageID != TEE_STORAGE_PRIVATE) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (objectID == NULL) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (objectIDLen > TEE_OBJECT_ID_MAX_LEN) + TEE_Panic(0); + + if (object == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + return utee_storage_obj_open(storageID, objectID, objectIDLen, flags, + object); +} + +TEE_Result TEE_CreatePersistentObject(uint32_t storageID, void *objectID, + size_t objectIDLen, uint32_t flags, + TEE_ObjectHandle attributes, + const void *initialData, + size_t initialDataLen, + TEE_ObjectHandle *object) +{ + if (storageID != TEE_STORAGE_PRIVATE) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (objectID == NULL) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (objectIDLen > TEE_OBJECT_ID_MAX_LEN) + TEE_Panic(0); + + if (object == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + return utee_storage_obj_create(storageID, objectID, objectIDLen, flags, + attributes, initialData, initialDataLen, + object); +} + +void TEE_CloseAndDeletePersistentObject(TEE_ObjectHandle object) +{ + TEE_Result res; + + if (object == TEE_HANDLE_NULL) + return; + + res = utee_storage_obj_del(object); + + if (res != TEE_SUCCESS) + TEE_Panic(0); +} + +TEE_Result TEE_RenamePersistentObject(TEE_ObjectHandle object, + const void *newObjectID, + size_t newObjectIDLen) +{ + TEE_Result res; + + if (object == TEE_HANDLE_NULL) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (newObjectID == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + if (newObjectIDLen > TEE_OBJECT_ID_MAX_LEN) + TEE_Panic(0); + + res = utee_storage_obj_rename(object, newObjectID, newObjectIDLen); + + if (res != TEE_SUCCESS && res != TEE_ERROR_ACCESS_CONFLICT) + TEE_Panic(0); + + return res; +} + +TEE_Result TEE_AllocatePersistentObjectEnumerator(TEE_ObjectEnumHandle * + objectEnumerator) +{ + TEE_Result res; + + if (objectEnumerator == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + res = utee_storage_alloc_enum(objectEnumerator); + + if (res != TEE_SUCCESS) + *objectEnumerator = TEE_HANDLE_NULL; + + return res; +} + +void TEE_FreePersistentObjectEnumerator(TEE_ObjectEnumHandle objectEnumerator) +{ + TEE_Result res; + + if (objectEnumerator == TEE_HANDLE_NULL) + return; + + res = utee_storage_free_enum(objectEnumerator); + + if (res != TEE_SUCCESS) + TEE_Panic(0); +} + +void TEE_ResetPersistentObjectEnumerator(TEE_ObjectEnumHandle objectEnumerator) +{ + TEE_Result res; + + if (objectEnumerator == TEE_HANDLE_NULL) + return; + + res = utee_storage_reset_enum(objectEnumerator); + + if (res != TEE_SUCCESS) + TEE_Panic(0); +} + +TEE_Result TEE_StartPersistentObjectEnumerator(TEE_ObjectEnumHandle + objectEnumerator, + uint32_t storageID) +{ + TEE_Result res; + + if (storageID != TEE_STORAGE_PRIVATE) + return TEE_ERROR_ITEM_NOT_FOUND; + + res = utee_storage_start_enum(objectEnumerator, storageID); + + if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND) + TEE_Panic(0); + + return res; +} + +TEE_Result TEE_GetNextPersistentObject(TEE_ObjectEnumHandle objectEnumerator, + TEE_ObjectInfo *objectInfo, + void *objectID, size_t *objectIDLen) +{ + TEE_Result res; + + res = + utee_storage_next_enum(objectEnumerator, objectInfo, objectID, + objectIDLen); + + if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND) + TEE_Panic(0); + + return res; +} + +/* Data and Key Storage API - Data Stream Access Functions */ + +TEE_Result TEE_ReadObjectData(TEE_ObjectHandle object, void *buffer, + size_t size, uint32_t *count) +{ + TEE_Result res; + + if (object == TEE_HANDLE_NULL) + TEE_Panic(0); + + res = utee_storage_obj_read(object, buffer, size, count); + + if (res != TEE_SUCCESS) + TEE_Panic(0); + + return res; +} + +TEE_Result TEE_WriteObjectData(TEE_ObjectHandle object, void *buffer, + size_t size) +{ + TEE_Result res; + + if (object == TEE_HANDLE_NULL) + TEE_Panic(0); + + res = utee_storage_obj_write(object, buffer, size); + + if (res != TEE_SUCCESS && res != TEE_ERROR_STORAGE_NO_SPACE) + TEE_Panic(0); + + return res; +} + +TEE_Result TEE_TruncateObjectData(TEE_ObjectHandle object, uint32_t size) +{ + TEE_Result res; + + if (object == TEE_HANDLE_NULL) + TEE_Panic(0); + + res = utee_storage_obj_trunc(object, size); + + if (res != TEE_SUCCESS && res != TEE_ERROR_STORAGE_NO_SPACE) + TEE_Panic(0); + + return res; +} + +TEE_Result TEE_SeekObjectData(TEE_ObjectHandle object, int32_t offset, + TEE_Whence whence) +{ + TEE_Result res; + TEE_ObjectInfo info; + + if (object == TEE_HANDLE_NULL) + TEE_Panic(0); + + res = utee_cryp_obj_get_info((uint32_t)object, &info); + if (res != TEE_SUCCESS) + TEE_Panic(0); + + switch (whence) { + case TEE_DATA_SEEK_SET: + if (offset > 0 && (uint32_t)offset > TEE_DATA_MAX_POSITION) + return TEE_ERROR_OVERFLOW; + break; + case TEE_DATA_SEEK_CUR: + if (offset > 0 && + ((uint32_t)offset + info.dataPosition > + TEE_DATA_MAX_POSITION || + (uint32_t)offset + info.dataPosition < + info.dataPosition)) + return TEE_ERROR_OVERFLOW; + break; + case TEE_DATA_SEEK_END: + if (offset > 0 && + ((uint32_t)offset + info.dataSize > TEE_DATA_MAX_POSITION || + (uint32_t)offset + info.dataSize < info.dataSize)) + return TEE_ERROR_OVERFLOW; + break; + default: + TEE_Panic(0); + } + + res = utee_storage_obj_seek(object, offset, whence); + + if (res != TEE_SUCCESS && res != TEE_ERROR_OVERFLOW) + TEE_Panic(0); + + return res; +} diff --git a/lib/libutee/tee_api_operations.c b/lib/libutee/tee_api_operations.c new file mode 100644 index 00000000000..b120ad2833d --- /dev/null +++ b/lib/libutee/tee_api_operations.c @@ -0,0 +1,1142 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include + +#include +#include +#include +#include + +struct __TEE_OperationHandle { + TEE_OperationInfo info; + TEE_ObjectHandle key1; + TEE_ObjectHandle key2; + uint8_t *buffer; /* buffer to collect complete blocks */ + bool buffer_two_blocks; /* True if two blocks need to be buffered */ + size_t block_size; /* Block size of cipher */ + size_t buffer_offs; /* Offset in buffer */ + uint32_t state; /* Handle to state in TEE Core */ + uint32_t ae_tag_len; /* + * tag_len in bytes for AE operation else unused + */ +}; + +/* Cryptographic Operations API - Generic Operation Functions */ + +TEE_Result TEE_AllocateOperation(TEE_OperationHandle *operation, + uint32_t algorithm, uint32_t mode, + uint32_t maxKeySize) +{ + TEE_Result res; + TEE_OperationHandle op = TEE_HANDLE_NULL; + uint32_t handle_state = 0; + size_t block_size = 1; + uint32_t req_key_usage; + bool with_private_key = false; + bool buffer_two_blocks = false; + + if (operation == NULL) + TEE_Panic(0); + + if (algorithm == TEE_ALG_AES_XTS) + handle_state = TEE_HANDLE_FLAG_EXPECT_TWO_KEYS; + + switch (algorithm) { + case TEE_ALG_AES_CTS: + case TEE_ALG_AES_XTS: + buffer_two_blocks = true; + /*FALLTHROUGH*/ case TEE_ALG_AES_ECB_NOPAD: + case TEE_ALG_AES_CBC_NOPAD: + case TEE_ALG_AES_CTR: + case TEE_ALG_AES_CCM: + case TEE_ALG_AES_GCM: + case TEE_ALG_DES_ECB_NOPAD: + case TEE_ALG_DES_CBC_NOPAD: + case TEE_ALG_DES3_ECB_NOPAD: + case TEE_ALG_DES3_CBC_NOPAD: + if (TEE_ALG_GET_MAIN_ALG(algorithm) == TEE_MAIN_ALGO_AES) + block_size = TEE_AES_BLOCK_SIZE; + else + block_size = TEE_DES_BLOCK_SIZE; + + if (mode == TEE_MODE_ENCRYPT) + req_key_usage = TEE_USAGE_ENCRYPT; + else if (mode == TEE_MODE_DECRYPT) + req_key_usage = TEE_USAGE_DECRYPT; + else + return TEE_ERROR_NOT_SUPPORTED; + break; + + case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: + case TEE_ALG_DSA_SHA1: + if (mode == TEE_MODE_SIGN) { + with_private_key = true; + req_key_usage = TEE_USAGE_SIGN; + } else if (mode == TEE_MODE_VERIFY) { + req_key_usage = TEE_USAGE_VERIFY; + } else { + return TEE_ERROR_NOT_SUPPORTED; + } + break; + + case TEE_ALG_RSAES_PKCS1_V1_5: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512: + if (mode == TEE_MODE_ENCRYPT) { + req_key_usage = TEE_USAGE_ENCRYPT; + } else if (mode == TEE_MODE_DECRYPT) { + with_private_key = true; + req_key_usage = TEE_USAGE_DECRYPT; + } else { + return TEE_ERROR_NOT_SUPPORTED; + } + break; + + case TEE_ALG_RSA_NOPAD: + if (mode == TEE_MODE_ENCRYPT) { + req_key_usage = TEE_USAGE_ENCRYPT | TEE_USAGE_VERIFY; + } else if (mode == TEE_MODE_DECRYPT) { + with_private_key = true; + req_key_usage = TEE_USAGE_DECRYPT | TEE_USAGE_SIGN; + } else { + return TEE_ERROR_NOT_SUPPORTED; + } + break; + + case TEE_ALG_DH_DERIVE_SHARED_SECRET: + if (mode != TEE_MODE_DERIVE) + return TEE_ERROR_NOT_SUPPORTED; + with_private_key = true; + req_key_usage = TEE_USAGE_DERIVE; + break; + + case TEE_ALG_MD5: + case TEE_ALG_SHA1: + case TEE_ALG_SHA224: + case TEE_ALG_SHA256: + case TEE_ALG_SHA384: + case TEE_ALG_SHA512: + if (mode != TEE_MODE_DIGEST) + return TEE_ERROR_NOT_SUPPORTED; + handle_state |= TEE_HANDLE_FLAG_KEY_SET; + req_key_usage = 0; + break; + + case TEE_ALG_DES_CBC_MAC_NOPAD: + case TEE_ALG_AES_CBC_MAC_NOPAD: + case TEE_ALG_AES_CBC_MAC_PKCS5: + case TEE_ALG_AES_CMAC: + case TEE_ALG_DES_CBC_MAC_PKCS5: + case TEE_ALG_DES3_CBC_MAC_NOPAD: + case TEE_ALG_DES3_CBC_MAC_PKCS5: + case TEE_ALG_HMAC_MD5: + case TEE_ALG_HMAC_SHA1: + case TEE_ALG_HMAC_SHA224: + case TEE_ALG_HMAC_SHA256: + case TEE_ALG_HMAC_SHA384: + case TEE_ALG_HMAC_SHA512: + if (mode != TEE_MODE_MAC) + return TEE_ERROR_NOT_SUPPORTED; + req_key_usage = TEE_USAGE_MAC; + break; + + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + op = TEE_Malloc(sizeof(*op), 0); + if (op == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + op->info.algorithm = algorithm; + op->info.operationClass = TEE_ALG_GET_CLASS(algorithm); + op->info.mode = mode; + op->info.maxKeySize = maxKeySize; + op->info.requiredKeyUsage = req_key_usage; + op->info.handleState = handle_state; + + if (block_size > 1) { + size_t buffer_size = block_size; + + if (buffer_two_blocks) + buffer_size *= 2; + + op->buffer = + TEE_Malloc(buffer_size, TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (op->buffer == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + } + op->block_size = block_size; + op->buffer_two_blocks = buffer_two_blocks; + + if (TEE_ALG_GET_CLASS(algorithm) != TEE_OPERATION_DIGEST) { + uint32_t mks = maxKeySize; + TEE_ObjectType key_type = TEE_ALG_GET_KEY_TYPE(algorithm, + with_private_key); + + /* + * If two keys are expected the max key size is the sum of + * the size of both keys. + */ + if (op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) + mks /= 2; + + res = TEE_AllocateTransientObject(key_type, mks, &op->key1); + if (res != TEE_SUCCESS) + goto out; + + if ((op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) != + 0) { + res = + TEE_AllocateTransientObject(key_type, mks, + &op->key2); + if (res != TEE_SUCCESS) + goto out; + } + } + + res = utee_cryp_state_alloc(algorithm, mode, (uint32_t) op->key1, + (uint32_t) op->key2, &op->state); + if (res != TEE_SUCCESS) + goto out; + + /* For multi-stage operation do an "init". */ + TEE_ResetOperation(op); + *operation = op; + +out: + if (res != TEE_SUCCESS) { + TEE_FreeTransientObject(op->key1); + TEE_FreeTransientObject(op->key2); + TEE_FreeOperation(op); + } + + return res; +} + +void TEE_FreeOperation(TEE_OperationHandle operation) +{ + if (operation != TEE_HANDLE_NULL) { + /* + * Note that keys should not be freed here, since they are + * claimed by the operation they will be freed by + * utee_cryp_state_free(). + */ + utee_cryp_state_free(operation->state); + TEE_Free(operation->buffer); + TEE_Free(operation); + } +} + +void TEE_GetOperationInfo(TEE_OperationHandle operation, + TEE_OperationInfo *operationInfo) +{ + if (operation == TEE_HANDLE_NULL) + TEE_Panic(0); + + if (operationInfo == NULL) + TEE_Panic(0); + + *operationInfo = operation->info; +} + +void TEE_ResetOperation(TEE_OperationHandle operation) +{ + TEE_Result res; + + if (operation == TEE_HANDLE_NULL) + TEE_Panic(0); + if (operation->info.operationClass == TEE_OPERATION_DIGEST) { + res = utee_hash_init(operation->state, NULL, 0); + if (res != TEE_SUCCESS) + TEE_Panic(res); + } + operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; +} + +TEE_Result TEE_SetOperationKey(TEE_OperationHandle operation, + TEE_ObjectHandle key) +{ + uint32_t key_size = 0; + + if (operation == TEE_HANDLE_NULL) + TEE_Panic(0); + + /* No key for digests */ + if (operation->info.operationClass == TEE_OPERATION_DIGEST) + TEE_Panic(0); + + /* Two keys expected */ + if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) != + 0) + TEE_Panic(0); + + if (key != TEE_HANDLE_NULL) { + TEE_ObjectInfo key_info; + + TEE_GetObjectInfo(key, &key_info); + /* Supplied key has to meet required usage */ + if ((key_info.objectUsage & operation->info.requiredKeyUsage) != + operation->info.requiredKeyUsage) { + TEE_Panic(0); + } + + if (operation->info.maxKeySize < key_info.objectSize) + TEE_Panic(0); + + key_size = key_info.objectSize; + } + + TEE_ResetTransientObject(operation->key1); + operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET; + + if (key != TEE_HANDLE_NULL) { + TEE_CopyObjectAttributes(operation->key1, key); + operation->info.handleState |= TEE_HANDLE_FLAG_KEY_SET; + } + + operation->info.keySize = key_size; + + return TEE_SUCCESS; +} + +TEE_Result TEE_SetOperationKey2(TEE_OperationHandle operation, + TEE_ObjectHandle key1, TEE_ObjectHandle key2) +{ + uint32_t key_size = 0; + + if (operation == TEE_HANDLE_NULL) + TEE_Panic(0); + + /* Two keys not expected */ + if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) == + 0) + TEE_Panic(0); + + /* Either both keys are NULL or both are not NULL */ + if ((key1 == TEE_HANDLE_NULL || key2 == TEE_HANDLE_NULL) && + key1 != key2) + TEE_Panic(0); + + if (key1 != TEE_HANDLE_NULL) { + TEE_ObjectInfo key_info1; + TEE_ObjectInfo key_info2; + + TEE_GetObjectInfo(key1, &key_info1); + /* Supplied key has to meet required usage */ + if ((key_info1.objectUsage & operation->info. + requiredKeyUsage) != operation->info.requiredKeyUsage) { + TEE_Panic(0); + } + + TEE_GetObjectInfo(key2, &key_info2); + /* Supplied key has to meet required usage */ + if ((key_info2.objectUsage & operation->info. + requiredKeyUsage) != operation->info.requiredKeyUsage) { + TEE_Panic(0); + } + + /* + * AES-XTS (the only multi key algorithm supported, requires the + * keys to be of equal size. + */ + if (operation->info.algorithm == TEE_ALG_AES_XTS && + key_info1.objectSize != key_info2.objectSize) + TEE_Panic(0); + + if (operation->info.maxKeySize < key_info1.objectSize) + TEE_Panic(0); + + /* + * Odd that only the size of one key should be reported while + * size of two key are used when allocating the operation. + */ + key_size = key_info1.objectSize; + } + + TEE_ResetTransientObject(operation->key1); + TEE_ResetTransientObject(operation->key2); + operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET; + + if (key1 != TEE_HANDLE_NULL) { + TEE_CopyObjectAttributes(operation->key1, key1); + TEE_CopyObjectAttributes(operation->key2, key2); + operation->info.handleState |= TEE_HANDLE_FLAG_KEY_SET; + } + + operation->info.keySize = key_size; + + return TEE_SUCCESS; +} + +void TEE_CopyOperation(TEE_OperationHandle dst_op, TEE_OperationHandle src_op) +{ + TEE_Result res; + + if (dst_op == TEE_HANDLE_NULL || src_op == TEE_HANDLE_NULL) + TEE_Panic(0); + if (dst_op->info.algorithm != src_op->info.algorithm) + TEE_Panic(0); + if (src_op->info.operationClass != TEE_OPERATION_DIGEST) { + TEE_ObjectHandle key1 = TEE_HANDLE_NULL; + TEE_ObjectHandle key2 = TEE_HANDLE_NULL; + + if (src_op->info.handleState & TEE_HANDLE_FLAG_KEY_SET) { + key1 = src_op->key1; + key2 = src_op->key2; + } + + if ((src_op->info.handleState & + TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) == 0) { + TEE_SetOperationKey(dst_op, key1); + } else { + TEE_SetOperationKey2(dst_op, key1, key2); + } + } + dst_op->info.handleState = src_op->info.handleState; + dst_op->info.keySize = src_op->info.keySize; + + if (dst_op->buffer_two_blocks != src_op->buffer_two_blocks || + dst_op->block_size != src_op->block_size) + TEE_Panic(0); + + if (dst_op->buffer != NULL) { + if (src_op->buffer == NULL) + TEE_Panic(0); + + memcpy(dst_op->buffer, src_op->buffer, src_op->buffer_offs); + dst_op->buffer_offs = src_op->buffer_offs; + } else if (src_op->buffer != NULL) { + TEE_Panic(0); + } + + res = utee_cryp_state_copy(dst_op->state, src_op->state); + if (res != TEE_SUCCESS) + TEE_Panic(res); +} + +/* Cryptographic Operations API - Message Digest Functions */ + +void TEE_DigestUpdate(TEE_OperationHandle operation, + void *chunk, size_t chunkSize) +{ + TEE_Result res; + + if (operation == TEE_HANDLE_NULL || chunk == NULL) + TEE_Panic(0); + if (operation->info.operationClass != TEE_OPERATION_DIGEST) + TEE_Panic(0); + res = utee_hash_update(operation->state, chunk, chunkSize); + if (res != TEE_SUCCESS) + TEE_Panic(res); +} + +TEE_Result TEE_DigestDoFinal(TEE_OperationHandle operation, const void *chunk, + size_t chunkLen, void *hash, size_t *hashLen) +{ + if (operation == TEE_HANDLE_NULL || (chunk == NULL && chunkLen != 0) || + hash == NULL || hashLen == NULL) + TEE_Panic(0); + if (operation->info.operationClass != TEE_OPERATION_DIGEST) + TEE_Panic(0); + return utee_hash_final(operation->state, chunk, chunkLen, hash, + hashLen); +} + +/* Cryptographic Operations API - Symmetric Cipher Functions */ + +void TEE_CipherInit(TEE_OperationHandle operation, const void *IV, size_t IVLen) +{ + TEE_Result res; + + if (operation == TEE_HANDLE_NULL) + TEE_Panic(0); + if (operation->info.operationClass != TEE_OPERATION_CIPHER) + TEE_Panic(0); + res = utee_cipher_init(operation->state, IV, IVLen); + if (res != TEE_SUCCESS) + TEE_Panic(res); + operation->buffer_offs = 0; + operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; +} + +static TEE_Result tee_buffer_update( + TEE_OperationHandle op, + TEE_Result(*update_func) (uint32_t state, const void *src, + size_t slen, void *dst, size_t *dlen), + const void *src_data, size_t src_len, + void *dest_data, size_t *dest_len) +{ + TEE_Result res; + const uint8_t *src = src_data; + size_t slen = src_len; + uint8_t *dst = dest_data; + size_t dlen = *dest_len; + size_t acc_dlen = 0; + size_t tmp_dlen; + size_t l; + size_t buffer_size; + + if (op->buffer_two_blocks) + buffer_size = op->block_size * 2; + else + buffer_size = op->block_size; + + if (op->buffer_offs > 0) { + /* Fill up complete block */ + if (op->buffer_offs < op->block_size) + l = MIN(slen, op->block_size - op->buffer_offs); + else + l = MIN(slen, buffer_size - op->buffer_offs); + memcpy(op->buffer + op->buffer_offs, src, l); + op->buffer_offs += l; + src += l; + slen -= l; + if ((op->buffer_offs % op->block_size) != 0) + goto out; /* Nothing left to do */ + } + + /* If we can feed from buffer */ + if (op->buffer_offs > 0 && (op->buffer_offs + slen) > buffer_size) { + l = TEE_ROUNDUP(op->buffer_offs + slen - buffer_size, + op->block_size); + l = MIN(op->buffer_offs, l); + tmp_dlen = dlen; + res = update_func(op->state, op->buffer, l, dst, &tmp_dlen); + if (res != TEE_SUCCESS) + TEE_Panic(res); + dst += tmp_dlen; + dlen -= tmp_dlen; + acc_dlen += tmp_dlen; + op->buffer_offs -= l; + if (op->buffer_offs > 0) { + /* + * Slen is small enough to be contained in rest buffer. + */ + memcpy(op->buffer, op->buffer + l, buffer_size - l); + memcpy(op->buffer + op->buffer_offs, src, slen); + op->buffer_offs += slen; + goto out; /* Nothing left to do */ + } + } + + if (slen > buffer_size) { + /* Buffer is empty, feed as much as possible from src */ + if (TEE_ALIGNMENT_IS_OK(src, uint32_t)) { + l = TEE_ROUNDUP(slen - buffer_size + 1, op->block_size); + + tmp_dlen = dlen; + res = update_func(op->state, src, l, dst, &tmp_dlen); + if (res != TEE_SUCCESS) + TEE_Panic(res); + src += l; + slen -= l; + dst += tmp_dlen; + dlen -= tmp_dlen; + acc_dlen += tmp_dlen; + } else { + /* + * Supplied data isn't well aligned, we're forced to + * feed through the buffer. + */ + while (slen >= op->block_size) { + memcpy(op->buffer, src, op->block_size); + + tmp_dlen = dlen; + res = + update_func(op->state, op->buffer, + op->block_size, dst, &tmp_dlen); + if (res != TEE_SUCCESS) + TEE_Panic(res); + src += op->block_size; + slen -= op->block_size; + dst += tmp_dlen; + dlen -= tmp_dlen; + acc_dlen += tmp_dlen; + } + } + } + + /* Slen is small enough to be contained in buffer. */ + memcpy(op->buffer + op->buffer_offs, src, slen); + op->buffer_offs += slen; + +out: + *dest_len = acc_dlen; + return TEE_SUCCESS; +} + +TEE_Result TEE_CipherUpdate(TEE_OperationHandle op, const void *srcData, + size_t srcLen, void *destData, size_t *destLen) +{ + size_t req_dlen; + + if (op == TEE_HANDLE_NULL || (srcData == NULL && srcLen != 0) || + destLen == NULL || (destData == NULL && *destLen != 0)) + TEE_Panic(0); + if (op->info.operationClass != TEE_OPERATION_CIPHER) + TEE_Panic(0); + if ((op->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) + TEE_Panic(0); + + /* Calculate required dlen */ + req_dlen = ((op->buffer_offs + srcLen) / op->block_size) * + op->block_size; + if (op->buffer_two_blocks) { + if (req_dlen > op->block_size * 2) + req_dlen -= op->block_size * 2; + else + req_dlen = 0; + } + /* + * Check that required destLen is big enough before starting to feed + * data to the algorithm. Errors during feeding of data are fatal as we + * can't restore sync with this API. + */ + if (*destLen < req_dlen) { + *destLen = req_dlen; + return TEE_ERROR_SHORT_BUFFER; + } + + tee_buffer_update(op, utee_cipher_update, srcData, srcLen, destData, + destLen); + + return TEE_SUCCESS; +} + +TEE_Result TEE_CipherDoFinal(TEE_OperationHandle op, + const void *srcData, size_t srcLen, void *destData, + size_t *destLen) +{ + TEE_Result res; + uint8_t *dst = destData; + size_t acc_dlen = 0; + size_t tmp_dlen; + size_t req_dlen; + + if (op == TEE_HANDLE_NULL || (srcData == NULL && srcLen != 0) || + destLen == NULL || (destData == NULL && *destLen != 0)) + TEE_Panic(0); + if (op->info.operationClass != TEE_OPERATION_CIPHER) + TEE_Panic(0); + if ((op->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) + TEE_Panic(0); + + /* + * Check that the final block doesn't require padding for those + * algorithms that requires client to supply padding. + */ + if (op->info.algorithm == TEE_ALG_AES_ECB_NOPAD || + op->info.algorithm == TEE_ALG_AES_CBC_NOPAD || + op->info.algorithm == TEE_ALG_DES_ECB_NOPAD || + op->info.algorithm == TEE_ALG_DES_CBC_NOPAD || + op->info.algorithm == TEE_ALG_DES3_ECB_NOPAD || + op->info.algorithm == TEE_ALG_DES3_CBC_NOPAD) { + if (((op->buffer_offs + srcLen) % op->block_size) != 0) + return TEE_ERROR_BAD_PARAMETERS; + } + + /* + * Check that required destLen is big enough before starting to feed + * data to the algorithm. Errors during feeding of data are fatal as we + * can't restore sync with this API. + */ + req_dlen = op->buffer_offs + srcLen; + if (*destLen < req_dlen) { + *destLen = req_dlen; + return TEE_ERROR_SHORT_BUFFER; + } + + tmp_dlen = *destLen - acc_dlen; + tee_buffer_update(op, utee_cipher_update, srcData, srcLen, dst, + &tmp_dlen); + dst += tmp_dlen; + acc_dlen += tmp_dlen; + + tmp_dlen = *destLen - acc_dlen; + res = utee_cipher_final(op->state, op->buffer, op->buffer_offs, + dst, &tmp_dlen); + if (res != TEE_SUCCESS) + TEE_Panic(res); + acc_dlen += tmp_dlen; + + op->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; + *destLen = acc_dlen; + return TEE_SUCCESS; +} + +/* Cryptographic Operations API - MAC Functions */ + +void TEE_MACInit(TEE_OperationHandle operation, const void *IV, size_t IVLen) +{ + TEE_Result res; + + if (operation == TEE_HANDLE_NULL) + TEE_Panic(0); + if (IV == NULL && IVLen != 0) + TEE_Panic(0); + if (operation->info.operationClass != TEE_OPERATION_MAC) + TEE_Panic(0); + res = utee_hash_init(operation->state, IV, IVLen); + if (res != TEE_SUCCESS) + TEE_Panic(res); + operation->buffer_offs = 0; + operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; +} + +void TEE_MACUpdate(TEE_OperationHandle op, const void *chunk, size_t chunkSize) +{ + TEE_Result res; + + if (op == TEE_HANDLE_NULL || (chunk == NULL && chunkSize != 0)) + TEE_Panic(0); + if (op->info.operationClass != TEE_OPERATION_MAC) + TEE_Panic(0); + if ((op->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) + TEE_Panic(0); + + res = utee_hash_update(op->state, chunk, chunkSize); + if (res != TEE_SUCCESS) + TEE_Panic(res); +} + +TEE_Result TEE_MACComputeFinal(TEE_OperationHandle op, + const void *message, size_t messageLen, + void *mac, size_t *macLen) +{ + TEE_Result res; + + if (op == TEE_HANDLE_NULL || (message == NULL && messageLen != 0) || + mac == NULL || macLen == NULL) + TEE_Panic(0); + if (op->info.operationClass != TEE_OPERATION_MAC) + TEE_Panic(0); + if ((op->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) + TEE_Panic(0); + + res = utee_hash_final(op->state, message, messageLen, mac, macLen); + op->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; + return res; +} + +TEE_Result TEE_MACCompareFinal(TEE_OperationHandle operation, + const void *message, size_t messageLen, + const void *mac, size_t macLen) +{ + TEE_Result res; + uint8_t computed_mac[TEE_MAX_HASH_SIZE]; + size_t computed_mac_size = TEE_MAX_HASH_SIZE; + + res = TEE_MACComputeFinal(operation, message, messageLen, computed_mac, + &computed_mac_size); + if (res != TEE_SUCCESS) + return res; + if (computed_mac_size != macLen) + return TEE_ERROR_MAC_INVALID; + if (memcmp(mac, computed_mac, computed_mac_size) != 0) + return TEE_ERROR_MAC_INVALID; + /* don't leave this on stack */ + memset(computed_mac, 0, computed_mac_size); + return TEE_SUCCESS; +} + +/* Cryptographic Operations API - Authenticated Encryption Functions */ + +TEE_Result TEE_AEInit(TEE_OperationHandle op, const void *nonce, + size_t nonceLen, uint32_t tagLen, uint32_t AADLen, + uint32_t payloadLen) +{ + TEE_Result res; + + if (op == TEE_HANDLE_NULL || nonce == NULL) + TEE_Panic(0); + if (op->info.operationClass != TEE_OPERATION_AE) + TEE_Panic(0); + + /* + * AES-CCM tag len is specified by AES-CCM spec and handled in TEE Core + * in the implementation. But AES-GCM spec doesn't specify the tag len + * according to the same principle so we have to check here instead to + * be GP compliant. + */ + if (op->info.algorithm == TEE_ALG_AES_GCM) { + /* + * From GP spec: For AES-GCM, can be 128, 120, 112, 104, or 96 + */ + if (tagLen < 96 || tagLen > 128 || (tagLen % 8 != 0)) + return TEE_ERROR_NOT_SUPPORTED; + } + + res = utee_authenc_init(op->state, nonce, nonceLen, tagLen / 8, AADLen, + payloadLen); + if (res != TEE_SUCCESS) { + if (res != TEE_ERROR_NOT_SUPPORTED) + TEE_Panic(res); + return res; + } + op->ae_tag_len = tagLen / 8; + + op->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; + return TEE_SUCCESS; +} + +void TEE_AEUpdateAAD(TEE_OperationHandle op, const void *AADdata, + size_t AADdataLen) +{ + TEE_Result res; + + if (op == TEE_HANDLE_NULL || (AADdata == NULL && AADdataLen != 0)) + TEE_Panic(0); + if (op->info.operationClass != TEE_OPERATION_AE) + TEE_Panic(0); + if ((op->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) + TEE_Panic(0); + + res = utee_authenc_update_aad(op->state, AADdata, AADdataLen); + if (res != TEE_SUCCESS) + TEE_Panic(res); +} + +TEE_Result TEE_AEUpdate(TEE_OperationHandle op, const void *srcData, + size_t srcLen, void *destData, size_t *destLen) +{ + size_t req_dlen; + + if (op == TEE_HANDLE_NULL || (srcData == NULL && srcLen != 0) || + destLen == NULL || (destData == NULL && *destLen != 0)) + TEE_Panic(0); + if (op->info.operationClass != TEE_OPERATION_AE) + TEE_Panic(0); + if ((op->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) + TEE_Panic(0); + + /* + * Check that required destLen is big enough before starting to feed + * data to the algorithm. Errors during feeding of data are fatal as we + * can't restore sync with this API. + */ + req_dlen = TEE_ROUNDDOWN(op->buffer_offs + srcLen, op->block_size); + if (*destLen < req_dlen) { + *destLen = req_dlen; + return TEE_ERROR_SHORT_BUFFER; + } + + tee_buffer_update(op, utee_authenc_update_payload, srcData, srcLen, + destData, destLen); + + return TEE_SUCCESS; +} + +TEE_Result TEE_AEEncryptFinal(TEE_OperationHandle op, + const void *srcData, size_t srcLen, + void *destData, size_t *destLen, void *tag, + size_t *tagLen) +{ + TEE_Result res; + uint8_t *dst = destData; + size_t acc_dlen = 0; + size_t tmp_dlen; + size_t req_dlen; + + if (op == TEE_HANDLE_NULL || (srcData == NULL && srcLen != 0) || + destLen == NULL || (destData == NULL && *destLen != 0) || + tag == NULL || tagLen == NULL) + TEE_Panic(0); + if (op->info.operationClass != TEE_OPERATION_AE) + TEE_Panic(0); + if ((op->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) + TEE_Panic(0); + + /* + * Check that required destLen is big enough before starting to feed + * data to the algorithm. Errors during feeding of data are fatal as we + * can't restore sync with this API. + */ + req_dlen = op->buffer_offs + srcLen; + if (*destLen < req_dlen) { + *destLen = req_dlen; + return TEE_ERROR_SHORT_BUFFER; + } + + /* + * Need to check this before update_payload since sync would be lost if + * we return short buffer after that. + */ + if (*tagLen < op->ae_tag_len) { + *tagLen = op->ae_tag_len; + return TEE_ERROR_SHORT_BUFFER; + } + + tmp_dlen = *destLen - acc_dlen; + tee_buffer_update(op, utee_authenc_update_payload, srcData, srcLen, + dst, &tmp_dlen); + dst += tmp_dlen; + acc_dlen += tmp_dlen; + + tmp_dlen = *destLen - acc_dlen; + res = + utee_authenc_enc_final(op->state, op->buffer, op->buffer_offs, dst, + &tmp_dlen, tag, tagLen); + if (res != TEE_SUCCESS) + TEE_Panic(res); + acc_dlen += tmp_dlen; + + *destLen = acc_dlen; + op->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; + + return res; +} + +TEE_Result TEE_AEDecryptFinal(TEE_OperationHandle op, + const void *srcData, size_t srcLen, + void *destData, size_t *destLen, const void *tag, + size_t tagLen) +{ + TEE_Result res; + uint8_t *dst = destData; + size_t acc_dlen = 0; + size_t tmp_dlen; + size_t req_dlen; + + if (op == TEE_HANDLE_NULL || (srcData == NULL && srcLen != 0) || + destLen == NULL || (destData == NULL && *destLen != 0) || + (tag == NULL && tagLen != 0)) + TEE_Panic(0); + if (op->info.operationClass != TEE_OPERATION_AE) + TEE_Panic(0); + if ((op->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) + TEE_Panic(0); + + /* + * Check that required destLen is big enough before starting to feed + * data to the algorithm. Errors during feeding of data are fatal as we + * can't restore sync with this API. + */ + req_dlen = op->buffer_offs + srcLen; + if (*destLen < req_dlen) { + *destLen = req_dlen; + return TEE_ERROR_SHORT_BUFFER; + } + + tmp_dlen = *destLen - acc_dlen; + tee_buffer_update(op, utee_authenc_update_payload, srcData, srcLen, + dst, &tmp_dlen); + dst += tmp_dlen; + acc_dlen += tmp_dlen; + + tmp_dlen = *destLen - acc_dlen; + res = + utee_authenc_dec_final(op->state, op->buffer, op->buffer_offs, dst, + &tmp_dlen, tag, tagLen); + if (res != TEE_SUCCESS && res != TEE_ERROR_MAC_INVALID) + TEE_Panic(res); + /* Supplied tagLen should match what we initiated with */ + if (tagLen != op->ae_tag_len) + res = TEE_ERROR_MAC_INVALID; + + acc_dlen += tmp_dlen; + + *destLen = acc_dlen; + op->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; + + return res; +} + +/* Cryptographic Operations API - Asymmetric Functions */ + +TEE_Result TEE_AsymmetricEncrypt(TEE_OperationHandle op, + const TEE_Attribute *params, + uint32_t paramCount, const void *srcData, + size_t srcLen, void *destData, + size_t *destLen) +{ + TEE_Result res; + + if (op == TEE_HANDLE_NULL || (srcData == NULL && srcLen != 0) || + destLen == NULL || (destData == NULL && *destLen != 0)) + TEE_Panic(0); + if (paramCount != 0 && params == NULL) + TEE_Panic(0); + if (op->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER) + TEE_Panic(0); + if (op->info.mode != TEE_MODE_ENCRYPT) + TEE_Panic(0); + + res = utee_asymm_operate(op->state, params, paramCount, srcData, srcLen, + destData, destLen); + if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) + TEE_Panic(res); + return res; +} + +TEE_Result TEE_AsymmetricDecrypt(TEE_OperationHandle op, + const TEE_Attribute *params, + uint32_t paramCount, const void *srcData, + size_t srcLen, void *destData, + size_t *destLen) +{ + TEE_Result res; + + if (op == TEE_HANDLE_NULL || (srcData == NULL && srcLen != 0) || + destLen == NULL || (destData == NULL && *destLen != 0)) + TEE_Panic(0); + if (paramCount != 0 && params == NULL) + TEE_Panic(0); + if (op->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER) + TEE_Panic(0); + if (op->info.mode != TEE_MODE_DECRYPT) + TEE_Panic(0); + + res = utee_asymm_operate(op->state, params, paramCount, srcData, srcLen, + destData, destLen); + if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) + TEE_Panic(res); + return res; +} + +TEE_Result TEE_AsymmetricSignDigest(TEE_OperationHandle op, + const TEE_Attribute *params, + uint32_t paramCount, const void *digest, + size_t digestLen, void *signature, + size_t *signatureLen) +{ + TEE_Result res; + + if (op == TEE_HANDLE_NULL || (digest == NULL && digestLen != 0) || + signature == NULL || signatureLen == NULL) + TEE_Panic(0); + if (paramCount != 0 && params == NULL) + TEE_Panic(0); + if (op->info.operationClass != TEE_OPERATION_ASYMMETRIC_SIGNATURE) + TEE_Panic(0); + if (op->info.mode != TEE_MODE_SIGN) + TEE_Panic(0); + + res = + utee_asymm_operate(op->state, params, paramCount, digest, digestLen, + signature, signatureLen); + if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) + TEE_Panic(res); + return res; +} + +TEE_Result TEE_AsymmetricVerifyDigest(TEE_OperationHandle op, + const TEE_Attribute *params, + uint32_t paramCount, const void *digest, + size_t digestLen, const void *signature, + size_t signatureLen) +{ + TEE_Result res; + + if (op == TEE_HANDLE_NULL || (digest == NULL && digestLen != 0) || + (signature == NULL && signatureLen != 0)) + TEE_Panic(0); + if (paramCount != 0 && params == NULL) + TEE_Panic(0); + if (op->info.operationClass != TEE_OPERATION_ASYMMETRIC_SIGNATURE) + TEE_Panic(0); + if (op->info.mode != TEE_MODE_VERIFY) + TEE_Panic(0); + + res = + utee_asymm_verify(op->state, params, paramCount, digest, digestLen, + signature, signatureLen); + if (res != TEE_SUCCESS && res != TEE_ERROR_SIGNATURE_INVALID) + TEE_Panic(res); + return res; +} + +/* Cryptographic Operations API - Key Derivation Functions */ + +void TEE_DeriveKey(TEE_OperationHandle operation, + const TEE_Attribute *params, uint32_t paramCount, + TEE_ObjectHandle derivedKey) +{ + TEE_Result res; + TEE_ObjectInfo key_info; + + if (operation == TEE_HANDLE_NULL || derivedKey == 0) + TEE_Panic(0); + if (paramCount != 0 && params == NULL) + TEE_Panic(0); + + if (operation->info.algorithm != TEE_ALG_DH_DERIVE_SHARED_SECRET) + TEE_Panic(0); + + if (operation->info.operationClass != TEE_OPERATION_KEY_DERIVATION) + TEE_Panic(0); + if (operation->info.mode != TEE_MODE_DERIVE) + TEE_Panic(0); + if ((operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) == 0) + TEE_Panic(0); + + res = utee_cryp_obj_get_info((uint32_t) derivedKey, &key_info); + if (res != TEE_SUCCESS) + TEE_Panic(0); + + if (key_info.objectType != TEE_TYPE_GENERIC_SECRET) + TEE_Panic(0); + if ((key_info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) != 0) + TEE_Panic(0); + + if ((operation->info.algorithm == TEE_ALG_DH_DERIVE_SHARED_SECRET) && + (paramCount != 1 || + params[0].attributeID != TEE_ATTR_DH_PUBLIC_VALUE)) + TEE_Panic(0); + + res = utee_cryp_derive_key(operation->state, params, paramCount, + (uint32_t) derivedKey); + if (res != TEE_SUCCESS) + TEE_Panic(res); +} + +/* Cryptographic Operations API - Random Number Generation Functions */ + +void TEE_GenerateRandom(void *randomBuffer, size_t randomBufferLen) +{ + TEE_Result res; + + res = utee_cryp_random_number_generate(randomBuffer, randomBufferLen); + if (res != TEE_SUCCESS) + TEE_Panic(res); +} diff --git a/lib/libutee/tee_api_property.c b/lib/libutee/tee_api_property.c new file mode 100644 index 00000000000..c8bac0c1a35 --- /dev/null +++ b/lib/libutee/tee_api_property.c @@ -0,0 +1,555 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "string_ext.h" +#include "base64.h" + +#define PROP_STR_MAX 80 + +#define PROP_ENUMERATOR_NOT_STARTED 0xffffffff + +struct prop_enumerator { + uint32_t idx; + TEE_PropSetHandle prop_set; +}; + +struct prop_value { + enum user_ta_prop_type type; + union { + bool bool_val; + uint32_t int_val; + TEE_UUID uuid_val; + TEE_Identity identity_val; + char str_val[PROP_STR_MAX]; + } u; +}; + +typedef TEE_Result(*ta_propget_func_t) (struct prop_value *pv); + +struct prop_set { + const char *str; + ta_propget_func_t get; +}; + +static TEE_Result propget_gpd_ta_app_id(struct prop_value *pv) +{ + pv->type = USER_TA_PROP_TYPE_UUID; + return utee_get_property(UTEE_PROP_TA_APP_ID, &pv->u.uuid_val, + sizeof(pv->u.uuid_val)); +} + +static TEE_Result propget_gpd_client_identity(struct prop_value *pv) +{ + pv->type = USER_TA_PROP_TYPE_IDENTITY; + return utee_get_property(UTEE_PROP_CLIENT_ID, &pv->u.identity_val, + sizeof(pv->u.identity_val)); +} + +static TEE_Result propget_gpd_tee_api_version(struct prop_value *pv) +{ + pv->type = USER_TA_PROP_TYPE_STRING; + return utee_get_property(UTEE_PROP_TEE_API_VERSION, &pv->u.str_val, + sizeof(pv->u.str_val)); +} + +static TEE_Result propget_gpd_tee_description(struct prop_value *pv) +{ + pv->type = USER_TA_PROP_TYPE_STRING; + return utee_get_property(UTEE_PROP_TEE_DESCR, &pv->u.str_val, + sizeof(pv->u.str_val)); +} + +static TEE_Result propget_gpd_tee_device_id(struct prop_value *pv) +{ + pv->type = USER_TA_PROP_TYPE_UUID; + return utee_get_property(UTEE_PROP_TEE_DEV_ID, &pv->u.uuid_val, + sizeof(pv->u.uuid_val)); +} + +static TEE_Result propget_gpd_tee_sys_time_protection_level(struct prop_value + *pv) +{ + pv->type = USER_TA_PROP_TYPE_U32; + return utee_get_property(UTEE_PROP_TEE_SYS_TIME_PROT_LEVEL, + &pv->u.int_val, sizeof(pv->u.int_val)); +} + +static TEE_Result propget_gpd_tee_ta_time_protection_level(struct prop_value + *pv) +{ + pv->type = USER_TA_PROP_TYPE_U32; + return utee_get_property(UTEE_PROP_TEE_TA_TIME_PROT_LEVEL, + &pv->u.int_val, sizeof(pv->u.int_val)); +} + +static TEE_Result propget_gpd_tee_arith_max_big_int_size(struct prop_value *pv) +{ + pv->type = USER_TA_PROP_TYPE_U32; + return utee_get_property(UTEE_PROP_TEE_ARITH_MAX_BIG_INT_SIZE, + &pv->u.int_val, sizeof(pv->u.int_val)); +} + +static const struct prop_set propset_current_ta[] = { + {"gpd.ta.appID", propget_gpd_ta_app_id}, +}; + +static const size_t propset_current_ta_len = + sizeof(propset_current_ta) / sizeof(propset_current_ta[0]); + +static const struct prop_set propset_current_client[] = { + {"gpd.client.identity", propget_gpd_client_identity}, +}; + +static const size_t propset_current_client_len = + sizeof(propset_current_client) / sizeof(propset_current_client[0]); + +static const struct prop_set propset_implementation[] = { + {"gpd.tee.apiversion", propget_gpd_tee_api_version}, + {"gpd.tee.description", propget_gpd_tee_description}, + {"gpd.tee.deviceID", propget_gpd_tee_device_id}, + {"gpd.tee.systemTime.protectionLevel", + propget_gpd_tee_sys_time_protection_level}, + {"gpd.tee.TAPersistentTime.protectionLevel", + propget_gpd_tee_ta_time_protection_level}, + {"gpd.tee.arith.maxBigIntSize", propget_gpd_tee_arith_max_big_int_size}, +}; + +static const size_t propset_implementation_len = + sizeof(propset_implementation) / sizeof(propset_implementation[0]); + +static TEE_Result propset_get(TEE_PropSetHandle h, const struct prop_set **ps, + size_t *ps_len, + const struct user_ta_property **eps, + size_t *eps_len) +{ + if (h == TEE_PROPSET_CURRENT_TA) { + *ps = propset_current_ta; + *ps_len = propset_current_ta_len; + *eps = ta_props; + *eps_len = ta_num_props; + } else if (h == TEE_PROPSET_CURRENT_CLIENT) { + *ps = propset_current_client; + *ps_len = propset_current_client_len; + *eps = NULL; + *eps_len = 0; + } else if (h == TEE_PROPSET_TEE_IMPLEMENTATION) { + *ps = propset_implementation; + *ps_len = propset_implementation_len; + *eps = NULL; + *eps_len = 0; + } else { + return TEE_ERROR_ITEM_NOT_FOUND; + } + + return TEE_SUCCESS; +} + +static TEE_Result propget_get_ext_prop(const struct user_ta_property *ep, + struct prop_value *pv) +{ + size_t l; + + pv->type = ep->type; + switch (ep->type) { + case USER_TA_PROP_TYPE_BOOL: + l = sizeof(bool); + break; + case USER_TA_PROP_TYPE_U32: + l = sizeof(uint32_t); + break; + case USER_TA_PROP_TYPE_UUID: + l = sizeof(TEE_UUID); + break; + case USER_TA_PROP_TYPE_IDENTITY: + l = sizeof(TEE_Identity); + break; + case USER_TA_PROP_TYPE_STRING: + case USER_TA_PROP_TYPE_BINARY_BLOCK: + /* Handle too large strings by truncating them */ + strlcpy(pv->u.str_val, ep->value, sizeof(pv->u.str_val)); + return TEE_SUCCESS; + default: + return TEE_ERROR_GENERIC; + } + memcpy(&pv->u, ep->value, l); + return TEE_SUCCESS; +} + +static TEE_Result propget_get_property(TEE_PropSetHandle h, char *name, + struct prop_value *pv) +{ + TEE_Result res; + const struct prop_set *ps; + size_t ps_len; + const struct user_ta_property *eps; + size_t eps_len; + + if (h == TEE_PROPSET_CURRENT_TA || h == TEE_PROPSET_CURRENT_CLIENT || + h == TEE_PROPSET_TEE_IMPLEMENTATION) { + size_t n; + + res = propset_get(h, &ps, &ps_len, &eps, &eps_len); + if (res != TEE_SUCCESS) + return res; + + for (n = 0; n < ps_len; n++) { + if (strcmp(name, ps[n].str) == 0) + return ps[n].get(pv); + } + for (n = 0; n < eps_len; n++) { + if (strcmp(name, eps[n].name) == 0) + return propget_get_ext_prop(eps + n, pv); + } + return TEE_ERROR_ITEM_NOT_FOUND; + } else { + struct prop_enumerator *pe = (struct prop_enumerator *)h; + uint32_t idx = pe->idx; + + if (idx == PROP_ENUMERATOR_NOT_STARTED) + return TEE_ERROR_ITEM_NOT_FOUND; + + res = propset_get(pe->prop_set, &ps, &ps_len, &eps, &eps_len); + if (res != TEE_SUCCESS) + return res; + + if (idx < ps_len) + return ps[idx].get(pv); + + idx -= ps_len; + if (idx < eps_len) + return propget_get_ext_prop(eps + idx, pv); + + return TEE_ERROR_BAD_PARAMETERS; + } +} + +TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator, + char *name, char *valueBuffer, + size_t *valueBufferLen) +{ + TEE_Result res; + struct prop_value pv; + size_t l; + size_t bufferlen; + + if (valueBuffer == NULL || valueBufferLen == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + bufferlen = *valueBufferLen; + + res = propget_get_property(propsetOrEnumerator, name, &pv); + if (res != TEE_SUCCESS) + return res; + + switch (pv.type) { + case USER_TA_PROP_TYPE_BOOL: + l = strlcpy(valueBuffer, pv.u.bool_val ? "true" : "false", + bufferlen); + break; + + case USER_TA_PROP_TYPE_U32: + l = snprintf(valueBuffer, bufferlen, "%u", + (unsigned int)pv.u.int_val); + break; + + case USER_TA_PROP_TYPE_UUID: + l = snprintf(valueBuffer, bufferlen, + "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x", + (unsigned int)pv.u.uuid_val.timeLow, + pv.u.uuid_val.timeMid, + pv.u.uuid_val.timeHiAndVersion, + pv.u.uuid_val.clockSeqAndNode[0], + pv.u.uuid_val.clockSeqAndNode[1], + pv.u.uuid_val.clockSeqAndNode[2], + pv.u.uuid_val.clockSeqAndNode[3], + pv.u.uuid_val.clockSeqAndNode[4], + pv.u.uuid_val.clockSeqAndNode[5], + pv.u.uuid_val.clockSeqAndNode[6], + pv.u.uuid_val.clockSeqAndNode[7]); + break; + + case USER_TA_PROP_TYPE_IDENTITY: + l = snprintf(valueBuffer, bufferlen, + "%u:%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x", + (unsigned int)pv.u.identity_val.login, + (unsigned int)pv.u.identity_val.uuid.timeLow, + pv.u.identity_val.uuid.timeMid, + pv.u.identity_val.uuid.timeHiAndVersion, + pv.u.identity_val.uuid.clockSeqAndNode[0], + pv.u.identity_val.uuid.clockSeqAndNode[1], + pv.u.identity_val.uuid.clockSeqAndNode[2], + pv.u.identity_val.uuid.clockSeqAndNode[3], + pv.u.identity_val.uuid.clockSeqAndNode[4], + pv.u.identity_val.uuid.clockSeqAndNode[5], + pv.u.identity_val.uuid.clockSeqAndNode[6], + pv.u.identity_val.uuid.clockSeqAndNode[7]); + break; + + case USER_TA_PROP_TYPE_STRING: + case USER_TA_PROP_TYPE_BINARY_BLOCK: + l = strlcpy(valueBuffer, pv.u.str_val, bufferlen); + break; + + default: + return TEE_ERROR_BAD_FORMAT; + } + + /* The size "must account for the zero terminator" */ + *valueBufferLen = l + 1; + + if (l >= bufferlen) + return TEE_ERROR_SHORT_BUFFER; + + return TEE_SUCCESS; +} + +TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator, + char *name, bool *value) +{ + TEE_Result res; + struct prop_value pv; + + if (value == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + res = propget_get_property(propsetOrEnumerator, name, &pv); + if (res != TEE_SUCCESS) + return res; + + if (pv.type != USER_TA_PROP_TYPE_BOOL) + return TEE_ERROR_BAD_FORMAT; + + *value = pv.u.bool_val; + return TEE_SUCCESS; +} + +TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator, + char *name, uint32_t *value) +{ + TEE_Result res; + struct prop_value pv; + + if (value == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + res = propget_get_property(propsetOrEnumerator, name, &pv); + if (res != TEE_SUCCESS) + return res; + + if (pv.type != USER_TA_PROP_TYPE_U32) + return TEE_ERROR_BAD_FORMAT; + + *value = pv.u.int_val; + return TEE_SUCCESS; +} + +TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator, + char *name, void *valueBuffer, + size_t *valueBufferLen) +{ + TEE_Result res; + struct prop_value pv; + void *val; + int val_len; + + if (valueBuffer == NULL || valueBufferLen == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + res = propget_get_property(propsetOrEnumerator, name, &pv); + if (res != TEE_SUCCESS) + return res; + + if (pv.type != USER_TA_PROP_TYPE_BINARY_BLOCK) + return TEE_ERROR_BAD_FORMAT; + + val = pv.u.str_val; + val_len = strlen(val); + if (!base64_dec(val, val_len, valueBuffer, valueBufferLen)) + return TEE_ERROR_SHORT_BUFFER; + return TEE_SUCCESS; +} + +TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator, + char *name, TEE_UUID *value) +{ + TEE_Result res; + struct prop_value pv; + + if (value == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + res = propget_get_property(propsetOrEnumerator, name, &pv); + if (res != TEE_SUCCESS) + return res; + + if (pv.type != USER_TA_PROP_TYPE_UUID) + return TEE_ERROR_BAD_FORMAT; + + *value = pv.u.uuid_val; /* struct copy */ + return TEE_SUCCESS; +} + +TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator, + char *name, TEE_Identity *value) +{ + TEE_Result res; + struct prop_value pv; + + if (value == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + res = propget_get_property(propsetOrEnumerator, name, &pv); + if (res != TEE_SUCCESS) + return res; + + if (pv.type != USER_TA_PROP_TYPE_IDENTITY) + return TEE_ERROR_BAD_FORMAT; + + *value = pv.u.identity_val; /* struct copy */ + return TEE_SUCCESS; +} + +TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator) +{ + struct prop_enumerator *pe; + + if (enumerator == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + pe = TEE_Malloc(sizeof(struct prop_enumerator), + TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (pe == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + *enumerator = (TEE_PropSetHandle) pe; + TEE_ResetPropertyEnumerator(*enumerator); + return TEE_SUCCESS; +} + +void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator) +{ + struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; + + pe->idx = PROP_ENUMERATOR_NOT_STARTED; +} + +void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator) +{ + struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; + + TEE_Free(pe); +} + +void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator, + TEE_PropSetHandle propSet) +{ + struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; + + if (pe == NULL) + return; + + pe->idx = 0; + pe->prop_set = propSet; +} + +TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator, + void *nameBuffer, size_t *nameBufferLen) +{ + TEE_Result res; + struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; + const struct prop_set *ps; + size_t ps_len; + const struct user_ta_property *eps; + size_t eps_len; + size_t l; + const char *str; + size_t bufferlen; + + if (pe == NULL || nameBuffer == NULL || nameBufferLen == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + bufferlen = *nameBufferLen; + res = propset_get(pe->prop_set, &ps, &ps_len, &eps, &eps_len); + if (res != TEE_SUCCESS) + return res; + + if (pe->idx < ps_len) + str = ps[pe->idx].str; + else if ((pe->idx - ps_len) < eps_len) + str = ta_props[pe->idx - ps_len].name; + else + return TEE_ERROR_ITEM_NOT_FOUND; + + l = strlcpy(nameBuffer, str, bufferlen); + + /* The size "must account for the zero terminator" */ + *nameBufferLen = l + 1; + + if (l >= bufferlen) + return TEE_ERROR_SHORT_BUFFER; + + return TEE_SUCCESS; +} + +TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator) +{ + TEE_Result res; + struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; + uint32_t next_idx; + const struct prop_set *ps; + size_t ps_len; + const struct user_ta_property *eps; + size_t eps_len; + + if (pe == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + if (pe->idx == PROP_ENUMERATOR_NOT_STARTED) + return TEE_ERROR_ITEM_NOT_FOUND; + + res = propset_get(pe->prop_set, &ps, &ps_len, &eps, &eps_len); + if (res != TEE_SUCCESS) + return res; + + next_idx = pe->idx + 1; + pe->idx = next_idx; + if (next_idx >= (ps_len + eps_len)) + return TEE_ERROR_ITEM_NOT_FOUND; + + return TEE_SUCCESS; +} diff --git a/lib/libutee/tee_user_mem.c b/lib/libutee/tee_user_mem.c new file mode 100644 index 00000000000..924b7592b0e --- /dev/null +++ b/lib/libutee/tee_user_mem.c @@ -0,0 +1,538 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include + +#include +#include +#include + +#include +#include "tee_user_mem.h" +#include "utee_misc.h" + +#ifdef CFG_NO_USER_MALLOC_GARBAGE + +void *tee_user_mem_alloc(size_t len, uint32_t hint) +{ + uint8_t *p; + + switch (hint) { + case 0: +#if (CFG_TEE_CORE_USER_MEM_DEBUG == 1) + case TEE_USER_MEM_HINT_NO_FILL_ZERO: + break; +#endif + default: + EMSG("Invalid alloc hint [%X]", (unsigned int)hint); + return NULL; + } + + p = utee_malloc(len); + if (p == NULL) + return NULL; + + if (hint == 0) + memset(p, 0, len); +#if (CFG_TEE_CORE_USER_MEM_DEBUG == 1) + if (hint == (typeof(hint)) TEE_USER_MEM_HINT_NO_FILL_ZERO) + memset(p, 0xBB, len); +#endif + return p; +} + +void *tee_user_mem_realloc(void *buffer, size_t len) +{ + return utee_realloc(buffer, len); +} + +void tee_user_mem_free(void *buffer) +{ + utee_free(buffer); +} + +void tee_user_mem_mark_heap(void) +{ +} + +size_t tee_user_mem_check_heap(void) +{ + return 0; +} + +#else /* CFG_NO_USER_MALLOC_GARBAGE */ + +/* + * Manage and track the memory allocation in the libc heap of the user side (TA) + * Register all allocations and the current TA Provide a garbage api to delete + * all allocations of a given TA. + */ + +/* + * ARTIST is a magic number to be compliant to a allocation/free of 0 size. + */ +static const void *ARTIST = (void *)0x10; + +/* + * Link list definition for tracking the memory activity. + */ +struct user_mem_elem { + TAILQ_ENTRY(user_mem_elem) link; + size_t len; + uint32_t hint; +}; +TAILQ_HEAD(user_mem_head, user_mem_elem) user_mem_head = +TAILQ_HEAD_INITIALIZER(user_mem_head); + +/* + * Debug tools. + */ +#if (CFG_TEE_CORE_USER_MEM_DEBUG == 1) +struct tee_user_mem_stats { + int nb_alloc; + size_t size; +}; +static void tee_user_mem_status(struct tee_user_mem_stats *stats); + +/* Extra size of memory to add canary line check */ +static const size_t CANARY_LINE_SIZE = 1; +#else +static const size_t CANARY_LINE_SIZE; +#endif + +/* + * Accessors from an element of the list and its attribute. + */ +static inline void *buf_addr(const struct user_mem_elem *e) +{ + return (uint8_t *)e + sizeof(struct user_mem_elem); +} + +static inline size_t buf_size(const struct user_mem_elem *e) +{ + return e->len - sizeof(struct user_mem_elem) - CANARY_LINE_SIZE; +} + +static inline void *elem_addr(const void *buffer) +{ + return (uint8_t *)buffer - sizeof(struct user_mem_elem); +} + +/* + * Check if a given buffer address has been allocated with this tool. + */ +static int is_buffer_valid(void *buffer) +{ + struct user_mem_elem *e; + + TAILQ_FOREACH(e, &user_mem_head, link) { + if (buf_addr(e) == buffer) + return 1; + } + return 0; +} + +#if (CFG_TEE_CORE_USER_MEM_DEBUG == 1) +/* + * Common print of an element. + */ +#if (CFG_TEE_TA_LOG_LEVEL > 0) +static void print_buf(int tl, const char *func, int line, const char *prefix, + const struct user_mem_elem *e) +{ + dprintf_raw(tl, "%s:%d: %slink:[%p], buf:[%p:%d]\n", + func, line, prefix, (void *)e, buf_addr(e), buf_size(e)); +} + +#define PB(trace_level, prefix, elem) { print_buf(trace_level, __func__, \ + __LINE__, prefix, elem); } +#else +#define PB(trace_level, prefix, elem) (void)0 +#endif /* CFG_TEE_TA_LOG_LEVEL */ + +/* + * Heap mark to track leak. + * + * Can't use OS21 partition api to be compatible with TZ. + * + * Can't use generic mallinfo to dump the libc heap because the tee core + * use also this heap. + * + * So use a simple static var which is updated on tee_user_mem_ operations. + */ +static size_t heap_level; + +/* + * global stats to summarize memory activities cross TA's. + */ +static struct tee_user_mem_stats global_stats; + +static void heap_inc(size_t size) +{ + INMSG("%d", size); + heap_level += size; + + global_stats.nb_alloc++; + global_stats.size += size; + OUTMSG("%d", global_stats.size); +} + +static void heap_dec(size_t size) +{ + INMSG("%d %d", heap_level, size); + heap_level -= size; + + global_stats.nb_alloc--; + global_stats.size -= size; + OUTMSG("%d", global_stats.size); +} + +/* + * Check integrity of the buffer and the list. + */ +static int check_elem_end(struct user_mem_elem *e) +{ + uint8_t *cp = (uint8_t *)e; + + /* + * The following check detects storing off the end of the allocated + * space in the buffer by comparing the end of buffer checksum with the + * address of the buffer. + */ + if ((cp[e->len - CANARY_LINE_SIZE] != + ((((uintptr_t) cp) & 0xFF) ^ 0xC5))) { + PB(TRACE_ERROR, "Corrupted: ", e); + return 0; + } + + return 1; +} + +static int check_elem(struct user_mem_elem *ap) +{ + struct user_mem_elem *e; + + /* Validate queue links */ + if (ap == NULL) + return 0; + + assert(((uintptr_t) ap & 0x3) == 0); + + e = TAILQ_NEXT(ap, link); + if (e != NULL && TAILQ_PREV(e, user_mem_head, link) != ap) { + PB(TRACE_ERROR, "Orphaned: ", e); + return 0; + } + + e = TAILQ_PREV(ap, user_mem_head, link); + if (e != NULL && TAILQ_NEXT(e, link) != ap) { + PB(TRACE_ERROR, "Orphaned: ", e); + return 0; + } + + return check_elem_end(ap); +} + +/* Trap PC element are corrupted. */ +static int is_mem_coherent(void) +{ + struct user_mem_elem *e; + + TAILQ_FOREACH(e, &user_mem_head, link) { + if (!check_elem(e)) { + assert(0); + return 0; + } + } + return 1; +} + +#else /* CFG_TEE_CORE_USER_MEM_DEBUG */ +static void heap_inc(size_t size) +{ +} + +static void heap_dec(size_t size) +{ +} + +#define PB(trace_level, prefix, elem) do {} while (0) +#endif /* CFG_TEE_CORE_USER_MEM_DEBUG */ + +/* + * API methods + */ + +/* + * Allocate buffer, enqueing on the orphaned buffer tracking list. + */ +void *tee_user_mem_alloc(size_t len, uint32_t hint) +{ + INMSG("%d %p", (int)len, (void *)hint); + + uint8_t *cp; + void *buf = NULL; + + if ((int)len < 0) { + OUTMSG("0x0"); + return NULL; + } + + if (len == 0) { + OUTMSG("%p", ARTIST); + return (void *)ARTIST; + } + + size_t total_len = + len + sizeof(struct user_mem_elem) + CANARY_LINE_SIZE; + + /* Check hint */ + switch (hint) { + case 0: +#if (CFG_TEE_CORE_USER_MEM_DEBUG == 1) + case TEE_USER_MEM_HINT_NO_FILL_ZERO: +#endif + break; + default: + EMSG("Invalid alloc hint [%p]", (void *)hint); + OUTMSG("0x0"); + return NULL; + } + + cp = utee_malloc(total_len); + if (cp != NULL) { + struct user_mem_elem *e = (struct user_mem_elem *)(void *)cp; + e->len = total_len; + e->hint = hint; + heap_inc(total_len); + + /* Enqueue buffer on allocated list */ + TAILQ_INSERT_TAIL(&user_mem_head, e, link); + +#if (CFG_TEE_CORE_USER_MEM_DEBUG == 1) + /* Emplace end-clobber detector at end of buffer */ + cp[total_len - CANARY_LINE_SIZE] = + (((uintptr_t) cp) & 0xFF) ^ 0xC5; +#endif + + PB(TRACE_DEBUG, "Allocate: ", (void *)e); + + buf = buf_addr(e); + + if (hint == 0) + memset(buf, 0, len); +#if (CFG_TEE_CORE_USER_MEM_DEBUG == 1) + else if (hint == (typeof(hint)) TEE_USER_MEM_HINT_NO_FILL_ZERO) + /* Fill buffer with init pattern */ + memset(buf, 0xBB, len); +#endif + } + + OUTMSG("[%p]", buf); + return buf; +} + +/* + * Adjust the size of a previously allocated buffer. Because of the need to + * maintain our control storage, tee_user_mem_realloc() must always allocate a + * new block and copy the data in the old block. This may result in programs + * which make heavy use of realloc() running much slower than normally. + */ +void *tee_user_mem_realloc(void *buffer, size_t len) +{ + size_t olen; + void *buf; + struct user_mem_elem *e; + + INMSG("[%p:%d]", buffer, (int)len); + + if ((int)len < 0) { + OUTMSG("0x0"); + return NULL; + } + + /* If the old block pointer + * - is NULL, + * - or was allocated with a zero size, + * - or invalid buffer + * treat realloc() as a malloc(). */ + if (buffer == NULL || buffer == ARTIST || !is_buffer_valid(buffer)) { + buf = tee_user_mem_alloc(len, DEFAULT_TEE_MALLOC_HINT); + OUTMSG("%p", buf); + return buf; + } + + /* + * If the old and new sizes are the same, be a nice guy and just return + * the buffer passed in. + */ + e = (struct user_mem_elem *)elem_addr(buffer); + olen = buf_size(e); + if (len == olen) { + OUTMSG("[%p]", buffer); + return buffer; + } + + /* + * Sizes differ. Allocate a new buffer of the requested size. If we + * can't obtain such a buffer, return NULL from realloc() and leave the + * buffer in ptr intact. + */ + buf = tee_user_mem_alloc(len, e->hint); + if (buf != NULL) { + memcpy(buf, buffer, MIN(len, olen)); + + /* All done. Free and dechain the original buffer. */ + tee_user_mem_free(buffer); + } + + OUTMSG("[%p]", buf); + return buf; +} + +/* + * Update free pool availability. free is never called except through this + * interface. free(x) is defined to generate a call to this routine. + */ +void tee_user_mem_free(void *buffer) +{ + INMSG("[%p]", buffer); + + /* It is OK to free NULL */ + if (buffer == NULL || buffer == ARTIST) + return; + + /* Check if the buffer is valid */ + if (!is_buffer_valid(buffer)) { + EMSG("unknown freed buffer [%p]", buffer); + return; + } + + uint8_t *cp = elem_addr(buffer); + + struct user_mem_elem *e = (struct user_mem_elem *)(void *)cp; + + PB(TRACE_DEBUG, "Free: ", (void *)e); + +#if (CFG_TEE_CORE_USER_MEM_DEBUG == 1) + assert(check_elem(e)); +#endif + + TAILQ_REMOVE(&user_mem_head, e, link); + + heap_dec(e->len); + +#if (CFG_TEE_CORE_USER_MEM_DEBUG == 1) + /* + * Now we wipe the contents of the just-released buffer with "designer + * garbage" (Duff Kurland's phrase) of alternating bits. This is + * intended to ruin the day for any miscreant who attempts to access + * data through a pointer into storage that's been previously released. + */ + memset(cp, 0xAA, e->len); +#endif + + utee_free(cp); + + OUTMSG(); +} + +#if (CFG_TEE_CORE_USER_MEM_DEBUG == 1) +/* + * Accessors to mark the heap. + */ +void tee_user_mem_mark_heap(void) +{ + INMSG(); + /* Reset the marker */ + heap_level = 0; + OUTMSG(); +} + +/* + * Accessors to check the heap and the whole list. + * Return 0 means no leak and link list is valid. + * Return >0 return nb bytes of leak. + */ +size_t tee_user_mem_check_heap(void) +{ + int res = 0; + INMSG("%d", heap_level); + + if (heap_level) { + EMSG("ta heap has changed of [%d]", heap_level); + OUTMSG("%d", heap_level); + return heap_level; + } + + res = !is_mem_coherent(); + + OUTMSG("%d", res); + return res; +} + +/* + * Dump the stats and elements of the memory activity. + */ +void tee_user_mem_status(struct tee_user_mem_stats *stats) +{ + struct user_mem_elem *e; + if (stats != NULL) + memcpy(stats, &global_stats, sizeof(struct tee_user_mem_stats)); + + AMSG("Nb alloc:\t[%d]", global_stats.nb_alloc); + AMSG("Size:\t[%d]", global_stats.size); + + TAILQ_FOREACH(e, &user_mem_head, link) { + PB(TRACE_ALWAYS, "", e); + } +} +#else +void tee_user_mem_mark_heap(void) +{ +} + +size_t tee_user_mem_check_heap(void) +{ + return 0; +} +#endif /* CFG_TEE_CORE_USER_MEM_DEBUG */ + +/* + * Free memory allocated from a specific TA. + */ +void tee_user_mem_garbage(void) +{ +#if (CFG_TEE_CORE_USER_MEM_DEBUG == 1) + tee_user_mem_status(NULL); +#endif + + while (TAILQ_FIRST(&user_mem_head) != NULL) + tee_user_mem_free(buf_addr(TAILQ_FIRST(&user_mem_head))); +} + +#endif /* CFG_NO_USER_MALLOC_GARBAGE */ diff --git a/lib/libutee/tee_user_mem.h b/lib/libutee/tee_user_mem.h new file mode 100644 index 00000000000..66366c345f1 --- /dev/null +++ b/lib/libutee/tee_user_mem.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TEE_USER_MEM_H +#define TEE_USER_MEM_H + +#include + +void *tee_user_mem_alloc(size_t len, uint32_t hint); +void *tee_user_mem_realloc(void *buffer, size_t len); +void tee_user_mem_free(void *buffer); + +void tee_user_mem_garbage(void); + +/****************************************************************************** + * By default, the hint of a buffer is 0, means the buffer is fill with 0 + * after its allocation + */ +static const uint32_t DEFAULT_TEE_MALLOC_HINT = 0x0; + +#endif /* TEE_USER_MEM_H */ diff --git a/lib/libutee/utee_misc.h b/lib/libutee/utee_misc.h new file mode 100644 index 00000000000..73951810b4f --- /dev/null +++ b/lib/libutee/utee_misc.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef UTEE_MISC_H +#define UTEE_MISC_H + +unsigned int utee_get_ta_exec_id(void); + +/* platform wrapper for the malloc library */ +void *utee_malloc(size_t len); +void *utee_realloc(void *buffer, size_t len); +void *utee_calloc(size_t nb, size_t len); +void utee_free(void *buffer); + +#endif diff --git a/lib/libutils/ext/include/string_ext.h b/lib/libutils/ext/include/string_ext.h new file mode 100644 index 00000000000..e284cbe2185 --- /dev/null +++ b/lib/libutils/ext/include/string_ext.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file provides extensions for functions not defined in + */ + +#ifndef STRING_EXT_H +#define STRING_EXT_H + +#include +#include + +/* + * Copy src to string dst of siz size. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t strlcpy(char *dst, const char *src, size_t size); +size_t strlcat(char *dst, const char *src, size_t size); + +#endif /* STRING_EXT_H */ diff --git a/lib/libutils/ext/strlcat.c b/lib/libutils/ext/strlcat.c new file mode 100644 index 00000000000..0a0361c54f7 --- /dev/null +++ b/lib/libutils/ext/strlcat.c @@ -0,0 +1,75 @@ +/* This file is copied from newlib-1.19 */ + +/* $OpenBSD: strlcat.c,v 1.8 2001/05/13 15:40:15 deraadt Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = + "$OpenBSD: strlcat.c,v 1.8 2001/05/13 15:40:15 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +/* #include */ + +size_t strlen(const char *s); +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +size_t strlcat(char *dst, const char *src, size_t siz) +{ + register char *d = dst; + register const char *s = src; + register size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return dlen + strlen(s); + + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return dlen + (s - src); /* count does not include NUL */ +} diff --git a/lib/libutils/ext/strlcpy.c b/lib/libutils/ext/strlcpy.c new file mode 100644 index 00000000000..99450c1d9a3 --- /dev/null +++ b/lib/libutils/ext/strlcpy.c @@ -0,0 +1,68 @@ +/* This file is copied from newlib-1.19 */ + +/* $OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = + "$OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t strlcpy(char *dst, const char *src, size_t siz) +{ + register char *d = dst; + register const char *s = src; + register size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) { + do { + if ((*d++ = *s++) == 0) + break; + } while (--n != 0); + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return s - src - 1; /* count does not include NUL */ +} diff --git a/lib/libutils/ext/sub.mk b/lib/libutils/ext/sub.mk new file mode 100644 index 00000000000..e8215a0f75a --- /dev/null +++ b/lib/libutils/ext/sub.mk @@ -0,0 +1,4 @@ +global-incdirs-y += include + +srcs-y += strlcat.c +srcs-y += strlcpy.c diff --git a/lib/libutils/isoc/arch/arm32/aeabi_divmod.c b/lib/libutils/isoc/arch/arm32/aeabi_divmod.c new file mode 100644 index 00000000000..d229c90ff73 --- /dev/null +++ b/lib/libutils/isoc/arch/arm32/aeabi_divmod.c @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Form ABI specifications: + * int __aeabi_idiv(int numerator, int denominator); + * unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator); + * + * typedef struct { int quot; int rem; } idiv_return; + * typedef struct { unsigned quot; unsigned rem; } uidiv_return; + * + * __value_in_regs idiv_return __aeabi_idivmod(int numerator, + * int *denominator); + * __value_in_regs uidiv_return __aeabi_uidivmod(unsigned *numerator, + * unsigned denominator); + */ + +/* struct qr - stores qutient/remainder to handle divmod EABI interfaces. */ +struct qr { + unsigned q; /* computed quotient */ + unsigned r; /* computed remainder */ + unsigned q_n; /* specficies if quotient shall be negative */ + unsigned r_n; /* specficies if remainder shall be negative */ +}; + +static void uint_div_qr(unsigned numerator, unsigned denominator, + struct qr *qr); + +/* returns in R0 and R1 by tail calling an asm function */ +unsigned __aeabi_uidivmod(unsigned numerator, unsigned denominator); + +unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator); +unsigned __aeabi_uimod(unsigned numerator, unsigned denominator); + +/* returns in R0 and R1 by tail calling an asm function */ +signed __aeabi_idivmod(signed numerator, signed denominator); + +signed __aeabi_idiv(signed numerator, signed denominator); +signed __aeabi_imod(signed numerator, signed denominator); + +/* + * __ste_idivmod_ret_t __aeabi_idivmod(signed numerator, signed denominator) + * Numerator and Denominator are received in R0 and R1. + * Where __ste_idivmod_ret_t is returned in R0 and R1. + * + * __ste_uidivmod_ret_t __aeabi_uidivmod(unsigned numerator, + * unsigned denominator) + * Numerator and Denominator are received in R0 and R1. + * Where __ste_uidivmod_ret_t is returned in R0 and R1. + */ +#ifdef __GNUC__ +signed ret_idivmod_values(signed quotient, signed remainder); +unsigned ret_uidivmod_values(unsigned quotient, unsigned remainder); +#else +#error "Compiler not supported" +#endif + +static void division_qr(int n, int p, struct qr *qr) +{ + int i = 0, q = 0; + if (p == 0) { + qr->r = 0xFFFFFFFF; /* division by 0 */ + return; + } + + if (n >= p) + i = (i << 1) + 1; /* increase size of q */ + + while (n>=(p<<1)) { + i = (i << 1) + 1; /* increase size of q */ + p = p << 1; /* increase p */ + } + + while (i>0) { + q = q << 1; /* write bit in q at index (size-1) */ + while (n >= p) + { + n -= p; + q++; + } + p = p >> 1; /* decrease p */ + i = i >> 1; /* decrease remaining size in q */ + } + qr->r = n; + qr->q = q; +} + +static void uint_div_qr(unsigned numerator, unsigned denominator, struct qr *qr) +{ + struct qr qr2; + + /* + * division_qr support dividing 31 bit unsigned numbers + * encoded on 32bit registers. In case value is to high, + * perform 2 divisions, one for each halves, and accumulate + * quotient and remainders. + */ + if (numerator & (1 << 31)) { + unsigned num = numerator >> 1; + division_qr(num, denominator, qr); + division_qr(num + (numerator & 1), denominator, &qr2); + qr->q += qr2.q; + qr->r += qr2.r; + if (qr->r >= denominator) { + qr->q++; + qr->r -= denominator; + } + if (qr->r >= denominator) { + qr->q++; + qr->r -= denominator; + } + } else { + division_qr(numerator, denominator, qr); + } + /* negate quotient and/or remainder according to requester */ + if (qr->q_n) + qr->q = -qr->q; + if (qr->r_n) + qr->r = -qr->r; +} + +unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator) +{ + struct qr qr = { .q_n = 0, .r_n = 0 }; + + uint_div_qr(numerator, denominator, &qr); + + return qr.q; +} + +unsigned __aeabi_uimod(unsigned numerator, unsigned denominator) +{ + struct qr qr = { .q_n = 0, .r_n = 0 }; + + uint_div_qr(numerator, denominator, &qr); + + return qr.r; +} + +unsigned __aeabi_uidivmod(unsigned numerator, unsigned denominator) +{ + struct qr qr = { .q_n = 0, .r_n = 0 }; + + uint_div_qr(numerator, denominator, &qr); + + return ret_uidivmod_values(qr.q, qr.r); +} + +signed __aeabi_idiv(signed numerator, signed denominator) +{ + struct qr qr = { .q_n = 0, .r_n = 0 }; + + if (((numerator < 0) && (denominator > 0)) || + ((numerator > 0) && (denominator < 0))) + qr.q_n = 1; /* quotient shall be negate */ + if (numerator < 0) { + numerator = -numerator; + qr.r_n = 1; /* remainder shall be negate */ + } + if (denominator < 0) + denominator = -denominator; + + uint_div_qr(numerator, denominator, &qr); + + return qr.q; +} + +signed __aeabi_imod(signed numerator, signed denominator) +{ + signed s; + signed i; + signed j; + signed h; + + struct qr qr = { .q_n = 0, .r_n = 0 }; + + /* in case modulo of a power of 2 */ + for (i = 0, j = 0, h = 0, s = denominator; (s != 0) || (h > 1); i++) { + if (s & 1) { + j = i; + h++; + } + s = s >> 1; + } + if (h == 1) + return numerator >> j; + + if (((numerator < 0) && (denominator > 0)) || + ((numerator > 0) && (denominator < 0))) + qr.q_n = 1; /* quotient shall be negate */ + if (numerator < 0) { + numerator = -numerator; + qr.r_n = 1; /* remainder shall be negate */ + } + if (denominator < 0) + denominator = -denominator; + + uint_div_qr(numerator, denominator, &qr); + + return qr.r; +} + +signed __aeabi_idivmod(signed numerator, signed denominator) +{ + struct qr qr = { .q_n = 0, .r_n = 0 }; + + if (((numerator < 0) && (denominator > 0)) || + ((numerator > 0) && (denominator < 0))) + qr.q_n = 1; /* quotient shall be negate */ + if (numerator < 0) { + numerator = -numerator; + qr.r_n = 1; /* remainder shall be negate */ + } + if (denominator < 0) + denominator = -denominator; + + uint_div_qr(numerator, denominator, &qr); + + return ret_idivmod_values(qr.q, qr.r); +} diff --git a/lib/libutils/isoc/arch/arm32/aeabi_divmod_asm.S b/lib/libutils/isoc/arch/arm32/aeabi_divmod_asm.S new file mode 100644 index 00000000000..1ea9129f307 --- /dev/null +++ b/lib/libutils/isoc/arch/arm32/aeabi_divmod_asm.S @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +.global ret_idivmod_values +.global ret_uidivmod_values + +.section .text +.balign 4 +.code 32 + +/* + * signed ret_idivmod_values(signed quot, signed rem); + * return quotient and remaining the EABI way (regs r0,r1) + */ +.func ret_idivmod_values +ret_idivmod_values: + bx lr +.endfunc + +/* + * unsigned ret_uidivmod_values(unsigned quot, unsigned rem); + * return quotient and remaining the EABI way (regs r0,r1) + */ +.func ret_uidivmod_values +ret_uidivmod_values: + bx lr +.endfunc diff --git a/lib/libutils/isoc/arch/arm32/sub.mk b/lib/libutils/isoc/arch/arm32/sub.mk new file mode 100644 index 00000000000..ec75ee3ada8 --- /dev/null +++ b/lib/libutils/isoc/arch/arm32/sub.mk @@ -0,0 +1,2 @@ +srcs-y += aeabi_divmod_asm.S +srcs-y += aeabi_divmod.c diff --git a/lib/libutils/isoc/dlmalloc.c b/lib/libutils/isoc/dlmalloc.c new file mode 100644 index 00000000000..a610be27f37 --- /dev/null +++ b/lib/libutils/isoc/dlmalloc.c @@ -0,0 +1,2475 @@ +/* + * dlmalloc configuration is defined at top of dlmalloc.h. + * config not revelant to exported dlmalloc.h header are defined below. + */ +/* redirect fprintf(stderr, ...) to teecore trace */ +#include +#define fprintf(h, fmt, ...) IMSG(fmt, __VA_ARGS__) +#include "dlmalloc.h" + +/* + A version of malloc/free/realloc written by Doug Lea and released to the + public domain. Send questions/comments/complaints/performance data + to dl@cs.oswego.edu + +* VERSION 2.6.6 Sun Mar 5 19:10:03 2000 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at + ftp://g.oswego.edu/pub/misc/malloc.c + Check before installing! + +* Why use this malloc? + + This is not the fastest, most space-conserving, most portable, or + most tunable malloc ever written. However it is among the fastest + while also being among the most space-conserving, portable and tunable. + Consistent balance across these factors results in a good general-purpose + allocator. For a high-level description, see + http://g.oswego.edu/dl/html/malloc.html + +* Synopsis of public routines + + (Much fuller descriptions are contained in the program documentation below.) + + malloc(size_t n); + Return a pointer to a newly allocated chunk of at least n bytes, or null + if no space is available. + free(Void_t* p); + Release the chunk of memory pointed to by p, or no effect if p is null. + realloc(Void_t* p, size_t n); + Return a pointer to a chunk of size n that contains the same data + as does chunk p up to the minimum of (n, p's size) bytes, or null + if no space is available. The returned pointer may or may not be + the same as p. If p is null, equivalent to malloc. Unless the + #define REALLOC_ZERO_BYTES_FREES below is set, realloc with a + size argument of zero (re)allocates a minimum-sized chunk. + memalign(size_t alignment, size_t n); + Return a pointer to a newly allocated chunk of n bytes, aligned + in accord with the alignment argument, which must be a power of + two. + valloc(size_t n); + Equivalent to memalign(pagesize, n), where pagesize is the page + size of the system (or as near to this as can be figured out from + all the includes/defines below.) + pvalloc(size_t n); + Equivalent to valloc(minimum-page-that-holds(n)), that is, + round up n to nearest pagesize. + calloc(size_t unit, size_t quantity); + Returns a pointer to quantity * unit bytes, with all locations + set to zero. + cfree(Void_t* p); + Equivalent to free(p). + malloc_trim(size_t pad); + Release all but pad bytes of freed top-most memory back + to the system. Return 1 if successful, else 0. + malloc_usable_size(Void_t* p); + Report the number usable allocated bytes associated with allocated + chunk p. This may or may not report more bytes than were requested, + due to alignment and minimum size constraints. + malloc_stats(); + Prints brief summary statistics on stderr. + mallinfo() + Returns (by copy) a struct containing various summary statistics. + mallopt(int parameter_number, int parameter_value) + Changes one of the tunable parameters described below. Returns + 1 if successful in changing the parameter, else 0. + +* Vital statistics: + + Alignment: 8-byte + 8 byte alignment is currently hardwired into the design. This + seems to suffice for all current machines and C compilers. + + Assumed pointer representation: 4 or 8 bytes + Code for 8-byte pointers is untested by me but has worked + reliably by Wolfram Gloger, who contributed most of the + changes supporting this. + + Assumed size_t representation: 4 or 8 bytes + Note that size_t is allowed to be 4 bytes even if pointers are 8. + + Minimum overhead per allocated chunk: 4 or 8 bytes + Each malloced chunk has a hidden overhead of 4 bytes holding size + and status information. + + Minimum allocated size: 4-byte ptrs: 16 bytes (including 4 overhead) + 8-byte ptrs: 24/32 bytes (including, 4/8 overhead) + + When a chunk is freed, 12 (for 4byte ptrs) or 20 (for 8 byte + ptrs but 4 byte size) or 24 (for 8/8) additional bytes are + needed; 4 (8) for a trailing size field + and 8 (16) bytes for free list pointers. Thus, the minimum + allocatable size is 16/24/32 bytes. + + Even a request for zero bytes (i.e., malloc(0)) returns a + pointer to something of the minimum allocatable size. + + Maximum allocated size: 4-byte size_t: 2^31 - 8 bytes + 8-byte size_t: 2^63 - 16 bytes + + It is assumed that (possibly signed) size_t bit values suffice to + represent chunk sizes. `Possibly signed' is due to the fact + that `size_t' may be defined on a system as either a signed or + an unsigned type. To be conservative, values that would appear + as negative numbers are avoided. + Requests for sizes with a negative sign bit when the request + size is treaded as a long will return null. + + Maximum overhead wastage per allocated chunk: normally 15 bytes + + Alignnment demands, plus the minimum allocatable size restriction + make the normal worst-case wastage 15 bytes (i.e., up to 15 + more bytes will be allocated than were requested in malloc), with + two exceptions: + 1. Because requests for zero bytes allocate non-zero space, + the worst case wastage for a request of zero bytes is 24 bytes. + 2. For requests >= mmap_threshold that are serviced via + mmap(), the worst case wastage is 8 bytes plus the remainder + from a system page (the minimal mmap unit); typically 4096 bytes. + +* Limitations + + Here are some features that are NOT currently supported + + * No user-definable hooks for callbacks and the like. + * No automated mechanism for fully checking that all accesses + to malloced memory stay within their bounds. + * No support for compaction. + +* Synopsis of compile-time options: + + People have reported using previous versions of this malloc on all + versions of Unix, sometimes by tweaking some of the defines + below. It has been tested most extensively on Solaris and + Linux. It is also reported to work on WIN32 platforms. + People have also reported adapting this malloc for use in + stand-alone embedded systems. + + The implementation is in straight, hand-tuned ANSI C. Among other + consequences, it uses a lot of macros. Because of this, to be at + all usable, this code should be compiled using an optimizing compiler + (for example gcc -O2) that can simplify expressions and control + paths. + + __STD_C (default: derived from C compiler defines) + Nonzero if using ANSI-standard C compiler, a C++ compiler, or + a C compiler sufficiently close to ANSI to get away with it. + DEBUG (default: NOT defined) + Define to enable debugging. Adds fairly extensive assertion-based + checking to help track down memory errors, but noticeably slows down + execution. + REALLOC_ZERO_BYTES_FREES (default: NOT defined) + Define this if you think that realloc(p, 0) should be equivalent + to free(p). Otherwise, since malloc returns a unique pointer for + malloc(0), so does realloc(p, 0). + HAVE_MEMCPY (default: defined) + Define if you are not otherwise using ANSI STD C, but still + have memcpy and memset in your C library and want to use them. + Otherwise, simple internal versions are supplied. + USE_MEMCPY (default: 1 if HAVE_MEMCPY is defined, 0 otherwise) + Define as 1 if you want the C library versions of memset and + memcpy called in realloc and calloc (otherwise macro versions are used). + At least on some platforms, the simple macro versions usually + outperform libc versions. + HAVE_MMAP (default: defined as 1) + Define to non-zero to optionally make malloc() use mmap() to + allocate very large blocks. + HAVE_MREMAP (default: defined as 0 unless Linux libc set) + Define to non-zero to optionally make realloc() use mremap() to + reallocate very large blocks. + malloc_getpagesize (default: derived from system #includes) + Either a constant or routine call returning the system page size. + HAVE_USR_INCLUDE_MALLOC_H (default: NOT defined) + Optionally define if you are on a system with a /usr/include/malloc.h + that declares struct mallinfo. It is not at all necessary to + define this even if you do, but will ensure consistency. + INTERNAL_SIZE_T (default: size_t) + Define to a 32-bit type (probably `unsigned int') if you are on a + 64-bit machine, yet do not want or need to allow malloc requests of + greater than 2^31 to be handled. This saves space, especially for + very small chunks. + INTERNAL_LINUX_C_LIB (default: NOT defined) + Defined only when compiled as part of Linux libc. + Also note that there is some odd internal name-mangling via defines + (for example, internally, `malloc' is named `mALLOc') needed + when compiling in this case. These look funny but don't otherwise + affect anything. + WIN32 (default: undefined) + Define this on MS win (95, nt) platforms to compile in sbrk emulation. + LACKS_UNISTD_H (default: undefined if not WIN32) + Define this if your system does not have a . + LACKS_SYS_PARAM_H (default: undefined if not WIN32) + Define this if your system does not have a . + MORECORE (default: sbrk) + The name of the routine to call to obtain more memory from the system. + MORECORE_FAILURE (default: -1) + The value returned upon failure of MORECORE. + MORECORE_CLEARS (default 1) + True (1) if the routine mapped to MORECORE zeroes out memory (which + holds for sbrk). + DEFAULT_TRIM_THRESHOLD + DEFAULT_TOP_PAD + DEFAULT_MMAP_THRESHOLD + DEFAULT_MMAP_MAX + Default values of tunable parameters (described in detail below) + controlling interaction with host system routines (sbrk, mmap, etc). + These values may also be changed dynamically via mallopt(). The + preset defaults are those that give best performance for typical + programs/systems. + USE_DL_PREFIX (default: undefined) + Prefix all public routines with the string 'dl'. Useful to + quickly avoid procedure declaration conflicts and linker symbol + conflicts with existing memory allocation routines. + + +*/ + +/* + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ST BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + Emulation of sbrk for WIN32 + All code within the ifdef WIN32 is untested by me. + + Thanks to Martin Fong and others for supplying this. +*/ + +#ifdef WIN32 + +#define AlignPage(add) (((add) + (malloc_getpagesize-1)) & \ +~(malloc_getpagesize-1)) +#define AlignPage64K(add) (((add) + (0x10000 - 1)) & ~(0x10000 - 1)) + +/* resrve 64MB to insure large contiguous space */ +#define RESERVED_SIZE (1024*1024*64) +#define NEXT_SIZE (2048*1024) +#define TOP_MEMORY ((unsigned long)2*1024*1024*1024) + +struct GmListElement; +typedef struct GmListElement GmListElement; + +struct GmListElement { + GmListElement *next; + void *base; +}; + +static GmListElement *head = 0; +static unsigned int gNextAddress = 0; +static unsigned int gAddressBase = 0; +static unsigned int gAllocatedSize = 0; + +static +GmListElement *makeGmListElement(void *bas) +{ + GmListElement *this; + this = (GmListElement *)(void *)LocalAlloc(0, sizeof(GmListElement)); + assert(this); + if (this) { + this->base = bas; + this->next = head; + head = this; + } + return this; +} + +void gcleanup() +{ + BOOL rval; + assert((head == NULL) || (head->base == (void *)gAddressBase)); + if (gAddressBase && (gNextAddress - gAddressBase)) { + rval = VirtualFree((void *)gAddressBase, + gNextAddress - gAddressBase, MEM_DECOMMIT); + assert(rval); + } + while (head) { + GmListElement *next = head->next; + rval = VirtualFree(head->base, 0, MEM_RELEASE); + assert(rval); + LocalFree(head); + head = next; + } +} + +static +void *findRegion(void *start_address, unsigned long size) +{ + MEMORY_BASIC_INFORMATION info; + if (size >= TOP_MEMORY) + return NULL; + + while ((unsigned long)start_address + size < TOP_MEMORY) { + VirtualQuery(start_address, &info, sizeof(info)); + if ((info.State == MEM_FREE) && (info.RegionSize >= size)) + return start_address; + else { + /* Requested region is not available so see if the */ + /* next region is available. Set 'start_address' */ + /* to the next region and call 'VirtualQuery()' */ + /* again. */ + + start_address = + (char *)info.BaseAddress + info.RegionSize; + + /* Make sure we start looking for the next region */ + /* on the *next* 64K boundary. Otherwise, even if */ + /* the new region is free according to */ + /* 'VirtualQuery()', the subsequent call to */ + /* 'VirtualAlloc()' (which follows the call to */ + /* this routine in 'wsbrk()') will round *down* */ + /* the requested address to a 64K boundary which */ + /* we already know is an address in the */ + /* unavailable region. Thus, the subsequent call */ + /* to 'VirtualAlloc()' will fail and bring us back */ + /* here, causing us to go into an infinite loop. */ + + start_address = + (void *)AlignPage64K((unsigned long)start_address); + } + } + return NULL; + +} + +void *wsbrk(long size) +{ + void *tmp; + if (size > 0) { + if (gAddressBase == 0) { + gAllocatedSize = max(RESERVED_SIZE, AlignPage(size)); + gNextAddress = gAddressBase = + (unsigned int)VirtualAlloc(NULL, gAllocatedSize, + MEM_RESERVE, + PAGE_NOACCESS); + } else if (AlignPage(gNextAddress + size) > + (gAddressBase + gAllocatedSize)) { + long new_size = max(NEXT_SIZE, AlignPage(size)); + void *new_address = + (void *)(gAddressBase + gAllocatedSize); + do { + new_address = findRegion(new_address, new_size); + + if (new_address == 0) + return (void *)-1; + + gAddressBase = gNextAddress = + (unsigned int)VirtualAlloc(new_address, + new_size, + MEM_RESERVE, + PAGE_NOACCESS); + /* repeat in case of race condition */ + /* The region that we found has been snagged */ + /* by another thread */ + } + while (gAddressBase == 0); + + assert(new_address == (void *)gAddressBase); + + gAllocatedSize = new_size; + + if (!makeGmListElement((void *)gAddressBase)) + return (void *)-1; + } + if ((size + gNextAddress) > AlignPage(gNextAddress)) { + void *res; + res = VirtualAlloc((void *)AlignPage(gNextAddress), + (size + gNextAddress - + AlignPage(gNextAddress)), + MEM_COMMIT, PAGE_READWRITE); + if (res == 0) + return (void *)-1; + } + tmp = (void *)gNextAddress; + gNextAddress = (unsigned int)tmp + size; + return tmp; + } else if (size < 0) { + unsigned int alignedGoal = AlignPage(gNextAddress + size); + /* Trim by releasing the virtual memory */ + if (alignedGoal >= gAddressBase) { + VirtualFree((void *)alignedGoal, + gNextAddress - alignedGoal, MEM_DECOMMIT); + gNextAddress = gNextAddress + size; + return (void *)gNextAddress; + } else { + VirtualFree((void *)gAddressBase, + gNextAddress - gAddressBase, MEM_DECOMMIT); + gNextAddress = gAddressBase; + return (void *)-1; + } + } else { + return (void *)gNextAddress; + } +} + +#endif + +/* + Type declarations +*/ + +struct malloc_chunk { + INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */ + INTERNAL_SIZE_T size; /* Size in bytes, including overhead. */ + struct malloc_chunk *fd; /* double links -- used only if free. */ + struct malloc_chunk *bk; +}; + +typedef struct malloc_chunk *mchunkptr; + +/* + + malloc_chunk details: + + (The following includes lightly edited explanations by Colin Plumb.) + + Chunks of memory are maintained using a `boundary tag' method as + described in e.g., Knuth or Standish. (See the paper by Paul + Wilson ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a + survey of such techniques.) Sizes of free chunks are stored both + in the front of each chunk and at the end. This makes + consolidating fragmented chunks into bigger chunks very fast. The + size fields also hold bits representing whether chunks are free or + in use. + + An allocated chunk looks like this: + + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of previous chunk, if allocated | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of chunk, in bytes |P| + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | User data starts here... . + . . + . (malloc_usable_space() bytes) . + . | +nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Where "chunk" is the front of the chunk for the purpose of most of + the malloc code, but "mem" is the pointer that is returned to the + user. "Nextchunk" is the beginning of the next contiguous chunk. + + Chunks always begin on even word boundries, so the mem portion + (which is returned to the user) is also on an even word boundary, and + thus double-word aligned. + + Free chunks are stored in circular doubly-linked lists, and look like this: + + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of previous chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `head:' | Size of chunk, in bytes |P| + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Forward pointer to next chunk in list | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Back pointer to previous chunk in list | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Unused space (may be 0 bytes long) . + . . + . | +nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `foot:' | Size of chunk, in bytes | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + The P (PREV_INUSE) bit, stored in the unused low-order bit of the + chunk size (which is always a multiple of two words), is an in-use + bit for the *previous* chunk. If that bit is *clear*, then the + word before the current chunk size contains the previous chunk + size, and can be used to find the front of the previous chunk. + (The very first chunk allocated always has this bit set, + preventing access to non-existent (or non-owned) memory.) + + Note that the `foot' of the current chunk is actually represented + as the prev_size of the NEXT chunk. (This makes it easier to + deal with alignments etc). + + The two exceptions to all this are + + 1. The special chunk `top', which doesn't bother using the + trailing size field since there is no + next contiguous chunk that would have to index off it. (After + initialization, `top' is forced to always exist. If it would + become less than MINSIZE bytes long, it is replenished via + malloc_extend_top.) + + 2. Chunks allocated via mmap, which have the second-lowest-order + bit (IS_MMAPPED) set in their size fields. Because they are + never merged or traversed from any other chunk, they have no + foot size or inuse information. + + Available chunks are kept in any of several places (all declared below): + + * `av': An array of chunks serving as bin headers for consolidated + chunks. Each bin is doubly linked. The bins are approximately + proportionally (log) spaced. There are a lot of these bins + (128). This may look excessive, but works very well in + practice. All procedures maintain the invariant that no + consolidated chunk physically borders another one. Chunks in + bins are kept in size order, with ties going to the + approximately least recently used chunk. + + The chunks in each bin are maintained in decreasing sorted order by + size. This is irrelevant for the small bins, which all contain + the same-sized chunks, but facilitates best-fit allocation for + larger chunks. (These lists are just sequential. Keeping them in + order almost never requires enough traversal to warrant using + fancier ordered data structures.) Chunks of the same size are + linked with the most recently freed at the front, and allocations + are taken from the back. This results in LRU or FIFO allocation + order, which tends to give each chunk an equal opportunity to be + consolidated with adjacent freed chunks, resulting in larger free + chunks and less fragmentation. + + * `top': The top-most available chunk (i.e., the one bordering the + end of available memory) is treated specially. It is never + included in any bin, is used only if no other chunk is + available, and is released back to the system if it is very + large (see M_TRIM_THRESHOLD). + + * `last_remainder': A bin holding only the remainder of the + most recently split (non-top) chunk. This bin is checked + before other non-fitting chunks, so as to provide better + locality for runs of sequentially allocated chunks. + + * Implicitly, through the host system's memory mapping tables. + If supported, requests greater than a threshold are usually + serviced via calls to mmap, and then later released via munmap. + +*/ + +/* sizes, alignments */ + +#define SIZE_SZ (sizeof(INTERNAL_SIZE_T)) +#define MALLOC_ALIGNMENT (SIZE_SZ + SIZE_SZ) +#define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1) +#define MINSIZE (sizeof(struct malloc_chunk)) + +/* conversion from malloc headers to user pointers, and back */ + +#define chunk2mem(p) ((Void_t*)((char*)(p) + 2*SIZE_SZ)) +#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ)) + +/* pad request bytes into a usable size */ + +#define request2size(req) \ + (((long)((req) + (SIZE_SZ + MALLOC_ALIGN_MASK)) < \ + (long)(MINSIZE + MALLOC_ALIGN_MASK)) ? MINSIZE : \ + (((req) + (SIZE_SZ + MALLOC_ALIGN_MASK)) & ~(MALLOC_ALIGN_MASK))) + +/* Check if m has acceptable alignment */ + +#define aligned_OK(m) (((unsigned long)((m)) & (MALLOC_ALIGN_MASK)) == 0) + +/* + Physical chunk operations +*/ + +/* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */ + +#define PREV_INUSE 0x1 + +/* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */ + +#define IS_MMAPPED 0x2 + +/* Bits to mask off when extracting size */ + +#define SIZE_BITS (PREV_INUSE|IS_MMAPPED) + +/* Ptr to next physical malloc_chunk. */ + +#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) )) + +/* Ptr to previous physical malloc_chunk */ + +#define prev_chunk(p)\ + ((mchunkptr)( ((char*)(p)) - ((p)->prev_size) )) + +/* Treat space at ptr + offset as a chunk */ + +#define chunk_at_offset(p, s) ((mchunkptr)(((char*)(p)) + (s))) + +/* + Dealing with use bits +*/ + +/* extract p's inuse bit */ + +#define inuse(p)\ +((((mchunkptr)(((char*)(p))+((p)->size & ~PREV_INUSE)))->size) & PREV_INUSE) + +/* extract inuse bit of previous chunk */ + +#define prev_inuse(p) ((p)->size & PREV_INUSE) + +/* check for mmap()'ed chunk */ + +#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED) + +/* set/clear chunk as in use without otherwise disturbing */ + +#define set_inuse(p)\ +((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size |= PREV_INUSE + +#define clear_inuse(p)\ +((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size &= ~(PREV_INUSE) + +/* check/set/clear inuse bits in known places */ + +#define inuse_bit_at_offset(p, s)\ + (((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE) + +#define set_inuse_bit_at_offset(p, s)\ + (((mchunkptr)(((char*)(p)) + (s)))->size |= PREV_INUSE) + +#define clear_inuse_bit_at_offset(p, s)\ + (((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE)) + +/* + Dealing with size fields +*/ + +/* Get size, ignoring use bits */ + +#define chunksize(p) ((p)->size & ~(SIZE_BITS)) + +/* Set size at head, without disturbing its use bit */ + +#define set_head_size(p, s) ((p)->size = (((p)->size & PREV_INUSE) | (s))) + +/* Set size/use ignoring previous bits in header */ + +#define set_head(p, s) ((p)->size = (s)) + +/* Set size at footer (only when chunk is not in use) */ + +#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_size = (s)) + +/* + Bins + + The bins, `av_' are an array of pairs of pointers serving as the + heads of (initially empty) doubly-linked lists of chunks, laid out + in a way so that each pair can be treated as if it were in a + malloc_chunk. (This way, the fd/bk offsets for linking bin heads + and chunks are the same). + + Bins for sizes < 512 bytes contain chunks of all the same size, spaced + 8 bytes apart. Larger bins are approximately logarithmically + spaced. (See the table below.) The `av_' array is never mentioned + directly in the code, but instead via bin access macros. + + Bin layout: + + 64 bins of size 8 + 32 bins of size 64 + 16 bins of size 512 + 8 bins of size 4096 + 4 bins of size 32768 + 2 bins of size 262144 + 1 bin of size what's left + + There is actually a little bit of slop in the numbers in bin_index + for the sake of speed. This makes no difference elsewhere. + + The special chunks `top' and `last_remainder' get their own bins, + (this is implemented via yet more trickery with the av_ array), + although `top' is never properly linked to its bin since it is + always handled specially. + +*/ + +#define NAV 128 /* number of bins */ + +typedef struct malloc_chunk *mbinptr; + +/* access macros */ + +#define bin_at(i) ((mbinptr)((char*)&(av_[2*(i) + 2]) - 2*SIZE_SZ)) +#define next_bin(b) ((mbinptr)((char*)(b) + 2 * sizeof(mbinptr))) +#define prev_bin(b) ((mbinptr)((char*)(b) - 2 * sizeof(mbinptr))) + +/* + The first 2 bins are never indexed. The corresponding av_ cells are instead + used for bookkeeping. This is not to save space, but to simplify + indexing, maintain locality, and avoid some initialization tests. +*/ + +#define top (bin_at(0)->fd) /* The topmost chunk */ +#define last_remainder (bin_at(1)) /* remainder from last split */ + +/* + Because top initially points to its own bin with initial + zero size, thus forcing extension on the first malloc request, + we avoid having any special code in malloc to check whether + it even exists yet. But we still need to in malloc_extend_top. +*/ + +#define initial_top ((mchunkptr)(bin_at(0))) + +/* Helper macro to initialize bins */ + +#define IAV(i) bin_at(i), bin_at(i) + +static mbinptr av_[NAV * 2 + 2] = { + NULL, NULL, + IAV(0), IAV(1), IAV(2), IAV(3), IAV(4), IAV(5), IAV(6), IAV(7), + IAV(8), IAV(9), IAV(10), IAV(11), IAV(12), IAV(13), IAV(14), IAV(15), + IAV(16), IAV(17), IAV(18), IAV(19), IAV(20), IAV(21), IAV(22), IAV(23), + IAV(24), IAV(25), IAV(26), IAV(27), IAV(28), IAV(29), IAV(30), IAV(31), + IAV(32), IAV(33), IAV(34), IAV(35), IAV(36), IAV(37), IAV(38), IAV(39), + IAV(40), IAV(41), IAV(42), IAV(43), IAV(44), IAV(45), IAV(46), IAV(47), + IAV(48), IAV(49), IAV(50), IAV(51), IAV(52), IAV(53), IAV(54), IAV(55), + IAV(56), IAV(57), IAV(58), IAV(59), IAV(60), IAV(61), IAV(62), IAV(63), + IAV(64), IAV(65), IAV(66), IAV(67), IAV(68), IAV(69), IAV(70), IAV(71), + IAV(72), IAV(73), IAV(74), IAV(75), IAV(76), IAV(77), IAV(78), IAV(79), + IAV(80), IAV(81), IAV(82), IAV(83), IAV(84), IAV(85), IAV(86), IAV(87), + IAV(88), IAV(89), IAV(90), IAV(91), IAV(92), IAV(93), IAV(94), IAV(95), + IAV(96), IAV(97), IAV(98), IAV(99), IAV(100), IAV(101), IAV(102), + IAV(103), + IAV(104), IAV(105), IAV(106), IAV(107), IAV(108), IAV(109), IAV(110), + IAV(111), + IAV(112), IAV(113), IAV(114), IAV(115), IAV(116), IAV(117), IAV(118), + IAV(119), + IAV(120), IAV(121), IAV(122), IAV(123), IAV(124), IAV(125), IAV(126), + IAV(127) +}; + +/* field-extraction macros */ + +#define first(b) ((b)->fd) +#define last(b) ((b)->bk) + +/* + Indexing into bins +*/ + +#define bin_index(sz) \ +(((((unsigned long)(sz)) >> 9) == 0) ? (((unsigned long)(sz)) >> 3): \ + ((((unsigned long)(sz)) >> 9) <= 4) ? 56 + (((unsigned long)(sz)) >> 6): \ + ((((unsigned long)(sz)) >> 9) <= 20) ? 91 + (((unsigned long)(sz)) >> 9): \ + ((((unsigned long)(sz)) >> 9) <= 84) ? 110 + (((unsigned long)(sz)) >> 12): \ + ((((unsigned long)(sz)) >> 9) <= 340) ? 119 + (((unsigned long)(sz)) >> 15): \ + ((((unsigned long)(sz)) >> 9) <= 1364) ? 124 + (((unsigned long)(sz)) >> 18): \ + 126) +/* + bins for chunks < 512 are all spaced 8 bytes apart, and hold + identically sized chunks. This is exploited in malloc. +*/ + +#define MAX_SMALLBIN 63 +#define MAX_SMALLBIN_SIZE 512 +#define SMALLBIN_WIDTH 8 + +#define smallbin_index(sz) (((unsigned long)(sz)) >> 3) + +/* + Requests are `small' if both the corresponding and the next bin are small +*/ + +#define is_small_request(nb) (nb < MAX_SMALLBIN_SIZE - SMALLBIN_WIDTH) + +/* + To help compensate for the large number of bins, a one-level index + structure is used for bin-by-bin searching. `binblocks' is a + one-word bitvector recording whether groups of BINBLOCKWIDTH bins + have any (possibly) non-empty bins, so they can be skipped over + all at once during during traversals. The bits are NOT always + cleared as soon as all bins in a block are empty, but instead only + when all are noticed to be empty during traversal in malloc. +*/ + +#define BINBLOCKWIDTH 4 /* bins per block */ + +#define binblocks (bin_at(0)->size) /* bitvector of nonempty blocks */ + +/* bin<->block macros */ + +#define idx2binblock(ix) ((unsigned)1 << (ix / BINBLOCKWIDTH)) +#define mark_binblock(ii) (binblocks |= idx2binblock(ii)) +#define clear_binblock(ii) (binblocks &= ~(idx2binblock(ii))) + +/* Other static bookkeeping data */ + +/* variables holding tunable values */ + +static unsigned long trim_threshold = DEFAULT_TRIM_THRESHOLD; +static unsigned long top_pad = DEFAULT_TOP_PAD; +static unsigned int n_mmaps_max = DEFAULT_MMAP_MAX; +static unsigned long mmap_threshold = DEFAULT_MMAP_THRESHOLD; + +/* The first value returned from sbrk */ +static char *sbrk_base = (char *)(-1); + +/* The maximum memory obtained from system via sbrk */ +static unsigned long max_sbrked_mem = 0; + +/* The maximum via either sbrk or mmap */ +static unsigned long max_total_mem = 0; + +/* internal working copy of mallinfo */ +static struct mallinfo current_mallinfo = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + +/* The total memory obtained from system via sbrk */ +#define sbrked_mem (current_mallinfo.arena) + +/* Tracking mmaps */ + +static unsigned int n_mmaps = 0; +static unsigned long mmapped_mem = 0; +#if HAVE_MMAP +static unsigned int max_n_mmaps = 0; +static unsigned long max_mmapped_mem = 0; +#endif + +/* + Debugging support +*/ + +#if DEBUG + +/* + These routines make a number of assertions about the states + of data structures that should be true at all times. If any + are not true, it's very likely that a user program has somehow + trashed memory. (It's also possible that there is a coding error + in malloc. In which case, please report it!) +*/ + +#if __STD_C +static void do_check_chunk(mchunkptr p) +#else +static void do_check_chunk(p) +mchunkptr p; +#endif +{ + INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE; + + /* No checkable chunk is mmapped */ + assert(!chunk_is_mmapped(p)); + + /* Check for legal address ... */ + assert((char *)p >= sbrk_base); + if (p != top) + assert((char *)p + sz <= (char *)top); + else + assert((char *)p + sz <= sbrk_base + sbrked_mem); + +} + +#if __STD_C +static void do_check_free_chunk(mchunkptr p) +#else +static void do_check_free_chunk(p) +mchunkptr p; +#endif +{ + INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE; + mchunkptr next = chunk_at_offset(p, sz); + + do_check_chunk(p); + + /* Check whether it claims to be free ... */ + assert(!inuse(p)); + + /* Unless a special marker, must have OK fields */ + if ((long)sz >= (long)MINSIZE) { + assert((sz & MALLOC_ALIGN_MASK) == 0); + assert(aligned_OK(chunk2mem(p))); + /* ... matching footer field */ + assert(next->prev_size == sz); + /* ... and is fully consolidated */ + assert(prev_inuse(p)); + assert(next == top || inuse(next)); + + /* ... and has minimally sane links */ + assert(p->fd->bk == p); + assert(p->bk->fd == p); + } else /* markers are always of size SIZE_SZ */ + assert(sz == SIZE_SZ); +} + +#if __STD_C +static void do_check_inuse_chunk(mchunkptr p) +#else +static void do_check_inuse_chunk(p) +mchunkptr p; +#endif +{ + mchunkptr next = next_chunk(p); + do_check_chunk(p); + + /* Check whether it claims to be in use ... */ + assert(inuse(p)); + + /* ... and is surrounded by OK chunks. + Since more things can be checked with free chunks than inuse ones, + if an inuse chunk borders them and debug is on, it's worth doing them. + */ + if (!prev_inuse(p)) { + mchunkptr prv = prev_chunk(p); + assert(next_chunk(prv) == p); + do_check_free_chunk(prv); + } + if (next == top) { + assert(prev_inuse(next)); + assert(chunksize(next) >= MINSIZE); + } else if (!inuse(next)) + do_check_free_chunk(next); + +} + +#if __STD_C +static void do_check_malloced_chunk(mchunkptr p, INTERNAL_SIZE_T s) +#else +static void do_check_malloced_chunk(p, s) +mchunkptr p; +INTERNAL_SIZE_T s; +#endif +{ + INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE; + long room = sz - s; + + do_check_inuse_chunk(p); + + /* Legal size ... */ + assert((long)sz >= (long)MINSIZE); + assert((sz & MALLOC_ALIGN_MASK) == 0); + assert(room >= 0); + assert(room < (long)MINSIZE); + + /* ... and alignment */ + assert(aligned_OK(chunk2mem(p))); + + /* ... and was allocated at front of an available chunk */ + assert(prev_inuse(p)); + +} + +#define check_free_chunk(P) do_check_free_chunk(P) +#define check_inuse_chunk(P) do_check_inuse_chunk(P) +#define check_chunk(P) do_check_chunk(P) +#define check_malloced_chunk(P,N) do_check_malloced_chunk(P,N) +#else +#define check_free_chunk(P) +#define check_inuse_chunk(P) +#define check_chunk(P) +#define check_malloced_chunk(P,N) +#endif + +/* + Macro-based internal utilities +*/ + +/* + Linking chunks in bin lists. + Call these only with variables, not arbitrary expressions, as arguments. +*/ + +/* + Place chunk p of size s in its bin, in size order, + putting it ahead of others of same size. +*/ + +#define frontlink(P, S, IDX, BK, FD) \ +{ \ + if (S < MAX_SMALLBIN_SIZE) \ + { \ + IDX = smallbin_index(S); \ + mark_binblock(IDX); \ + BK = bin_at(IDX); \ + FD = BK->fd; \ + P->bk = BK; \ + P->fd = FD; \ + FD->bk = BK->fd = P; \ + } \ + else \ + { \ + IDX = bin_index(S); \ + BK = bin_at(IDX); \ + FD = BK->fd; \ + if (FD == BK) mark_binblock(IDX); \ + else \ + { \ + while (FD != BK && S < chunksize(FD)) FD = FD->fd; \ + BK = FD->bk; \ + } \ + P->bk = BK; \ + P->fd = FD; \ + FD->bk = BK->fd = P; \ + } \ +} + +/* take a chunk off a list */ + +#define unlink(P, BK, FD) \ +{ \ + BK = P->bk; \ + FD = P->fd; \ + FD->bk = BK; \ + BK->fd = FD; \ +} \ + +/* Place p as the last remainder */ + +#define link_last_remainder(P) \ +{ \ + last_remainder->fd = last_remainder->bk = P; \ + P->fd = P->bk = last_remainder; \ +} + +/* Clear the last_remainder bin */ + +#define clear_last_remainder \ + (last_remainder->fd = last_remainder->bk = last_remainder) + +/* Routines dealing with mmap(). */ + +#if HAVE_MMAP + +#if __STD_C +static mchunkptr mmap_chunk(size_t size) +#else +static mchunkptr mmap_chunk(size) +size_t size; +#endif +{ + size_t page_mask = malloc_getpagesize - 1; + mchunkptr p; + +#ifndef MAP_ANONYMOUS + static int fd = -1; +#endif + + if (n_mmaps >= n_mmaps_max) + return 0; /* too many regions */ + + /* For mmapped chunks, the overhead is one SIZE_SZ unit larger, because + * there is no following chunk whose prev_size field could be used. + */ + size = (size + SIZE_SZ + page_mask) & ~page_mask; + +#ifdef MAP_ANONYMOUS + p = (mchunkptr) mmap(0, size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); +#else /* !MAP_ANONYMOUS */ + if (fd < 0) { + fd = open("/dev/zero", O_RDWR); + if (fd < 0) + return 0; + } + p = (mchunkptr) mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, + 0); +#endif + + if (p == (mchunkptr) - 1) + return 0; + + n_mmaps++; + if (n_mmaps > max_n_mmaps) + max_n_mmaps = n_mmaps; + + /* We demand that eight bytes into a page must be 8-byte aligned. */ + assert(aligned_OK(chunk2mem(p))); + + /* The offset to the start of the mmapped region is stored + * in the prev_size field of the chunk; normally it is zero, + * but that can be changed in memalign(). + */ + p->prev_size = 0; + set_head(p, size | IS_MMAPPED); + + mmapped_mem += size; + if ((unsigned long)mmapped_mem > (unsigned long)max_mmapped_mem) + max_mmapped_mem = mmapped_mem; + if ((unsigned long)(mmapped_mem + sbrked_mem) > + (unsigned long)max_total_mem) + max_total_mem = mmapped_mem + sbrked_mem; + return p; +} + +#if __STD_C +static void munmap_chunk(mchunkptr p) +#else +static void munmap_chunk(p) +mchunkptr p; +#endif +{ + INTERNAL_SIZE_T size = chunksize(p); + int ret; + + assert(chunk_is_mmapped(p)); + assert(!((char *)p >= sbrk_base && (char *)p < sbrk_base + sbrked_mem)); + assert((n_mmaps > 0)); + assert(((p->prev_size + size) & (malloc_getpagesize - 1)) == 0); + + n_mmaps--; + mmapped_mem -= (size + p->prev_size); + + ret = munmap((char *)p - p->prev_size, size + p->prev_size); + + /* munmap returns non-zero on failure */ + if (ret) + assert(ret == 0); +} + +#if HAVE_MREMAP + +#if __STD_C +static mchunkptr mremap_chunk(mchunkptr p, size_t new_size) +#else +static mchunkptr mremap_chunk(p, new_size) +mchunkptr p; +size_t new_size; +#endif +{ + size_t page_mask = malloc_getpagesize - 1; + INTERNAL_SIZE_T offset = p->prev_size; + INTERNAL_SIZE_T size = chunksize(p); + char *cp; + + assert(chunk_is_mmapped(p)); + assert(!((char *)p >= sbrk_base && (char *)p < sbrk_base + sbrked_mem)); + assert((n_mmaps > 0)); + assert(((size + offset) & (malloc_getpagesize - 1)) == 0); + + /* Note the extra SIZE_SZ overhead as in mmap_chunk(). */ + new_size = (new_size + offset + SIZE_SZ + page_mask) & ~page_mask; + + cp = (char *)mremap((char *)p - offset, size + offset, new_size, 1); + + if (cp == (char *)-1) + return 0; + + p = (mchunkptr) (cp + offset); + + assert(aligned_OK(chunk2mem(p))); + + assert((p->prev_size == offset)); + set_head(p, (new_size - offset) | IS_MMAPPED); + + mmapped_mem -= size + offset; + mmapped_mem += new_size; + if ((unsigned long)mmapped_mem > (unsigned long)max_mmapped_mem) + max_mmapped_mem = mmapped_mem; + if ((unsigned long)(mmapped_mem + sbrked_mem) > + (unsigned long)max_total_mem) + max_total_mem = mmapped_mem + sbrked_mem; + return p; +} + +#endif /* HAVE_MREMAP */ + +#endif /* HAVE_MMAP */ + +/* + Extend the top-most chunk by obtaining memory from system. + Main interface to sbrk (but see also malloc_trim). +*/ + +#if __STD_C +static void malloc_extend_top(INTERNAL_SIZE_T nb) +#else +static void malloc_extend_top(nb) +INTERNAL_SIZE_T nb; +#endif +{ + char *brk; /* return value from sbrk */ + INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of sbrked space */ + INTERNAL_SIZE_T correction; /* bytes for 2nd sbrk call */ + char *new_brk; /* return of 2nd sbrk call */ + INTERNAL_SIZE_T top_size; /* new size of top chunk */ + + mchunkptr old_top = top; /* Record state of old top */ + INTERNAL_SIZE_T old_top_size = chunksize(old_top); + char *old_end = (char *)(chunk_at_offset(old_top, old_top_size)); + + /* Pad request with top_pad plus minimal overhead */ + + INTERNAL_SIZE_T sbrk_size = nb + top_pad + MINSIZE; + unsigned long pagesz = malloc_getpagesize; + + /* If not the first time through, round to preserve page boundary */ + /* Otherwise, we need to correct to a page size below anyway. */ + /* (We also correct below if an intervening foreign sbrk call.) */ + + if (sbrk_base != (char *)(-1)) + sbrk_size = (sbrk_size + (pagesz - 1)) & ~(pagesz - 1); + + brk = (char *)(MORECORE(sbrk_size)); + + /* Fail if sbrk failed or if a foreign sbrk call killed our space */ + if (brk == (char *)(MORECORE_FAILURE) || + (brk < old_end && old_top != initial_top)) + return; + + sbrked_mem += sbrk_size; + + if (brk == old_end) { /* can just add bytes to current top */ + top_size = sbrk_size + old_top_size; + set_head(top, top_size | PREV_INUSE); + } else { + if (sbrk_base == (char *)(-1)) /* First time through. Record base */ + sbrk_base = brk; + else /* Someone else called sbrk(). Count those bytes as sbrked_mem. */ + sbrked_mem += brk - (char *)old_end; + + /* Guarantee alignment of first new chunk made from this space */ + front_misalign = + (unsigned long)chunk2mem(brk) & MALLOC_ALIGN_MASK; + if (front_misalign > 0) { + correction = (MALLOC_ALIGNMENT) - front_misalign; + brk += correction; + } else + correction = 0; + + /* Guarantee the next brk will be at a page boundary */ + + correction += + ((((unsigned long)(brk + sbrk_size)) + + (pagesz - 1)) & ~(pagesz - 1)) - ((unsigned long)(brk + + sbrk_size)); + + /* Allocate correction */ + new_brk = (char *)(MORECORE(correction)); + if (new_brk == (char *)(MORECORE_FAILURE)) + return; + + sbrked_mem += correction; + + top = (mchunkptr) brk; + top_size = new_brk - brk + correction; + set_head(top, top_size | PREV_INUSE); + + if (old_top != initial_top) { + + /* There must have been an intervening foreign sbrk call. */ + /* A double fencepost is necessary to prevent consolidation */ + + /* If not enough space to do this, then user did something very wrong */ + if (old_top_size < MINSIZE) { + set_head(top, PREV_INUSE); /* will force null return from malloc */ + return; + } + + /* Also keep size a multiple of MALLOC_ALIGNMENT */ + old_top_size = + (old_top_size - 3 * SIZE_SZ) & ~MALLOC_ALIGN_MASK; + set_head_size(old_top, old_top_size); + chunk_at_offset(old_top, old_top_size)->size = + SIZE_SZ | PREV_INUSE; + chunk_at_offset(old_top, old_top_size + SIZE_SZ)->size = + SIZE_SZ | PREV_INUSE; + /* If possible, release the rest. */ + if (old_top_size >= MINSIZE) + fREe(chunk2mem(old_top)); + } + } + + if ((unsigned long)sbrked_mem > (unsigned long)max_sbrked_mem) + max_sbrked_mem = sbrked_mem; + if ((unsigned long)(mmapped_mem + sbrked_mem) > + (unsigned long)max_total_mem) + max_total_mem = mmapped_mem + sbrked_mem; + + /* We always land on a page boundary */ + assert(((unsigned long)((char *)top + top_size) & (pagesz - 1)) == 0); +} + +/* Main public routines */ + +/* + Malloc Algorthim: + + The requested size is first converted into a usable form, `nb'. + This currently means to add 4 bytes overhead plus possibly more to + obtain 8-byte alignment and/or to obtain a size of at least + MINSIZE (currently 16 bytes), the smallest allocatable size. + (All fits are considered `exact' if they are within MINSIZE bytes.) + + From there, the first successful of the following steps is taken: + + 1. The bin corresponding to the request size is scanned, and if + a chunk of exactly the right size is found, it is taken. + + 2. The most recently remaindered chunk is used if it is big + enough. This is a form of (roving) first fit, used only in + the absence of exact fits. Runs of consecutive requests use + the remainder of the chunk used for the previous such request + whenever possible. This limited use of a first-fit style + allocation strategy tends to give contiguous chunks + coextensive lifetimes, which improves locality and can reduce + fragmentation in the long run. + + 3. Other bins are scanned in increasing size order, using a + chunk big enough to fulfill the request, and splitting off + any remainder. This search is strictly by best-fit; i.e., + the smallest (with ties going to approximately the least + recently used) chunk that fits is selected. + + 4. If large enough, the chunk bordering the end of memory + (`top') is split off. (This use of `top' is in accord with + the best-fit search rule. In effect, `top' is treated as + larger (and thus less well fitting) than any other available + chunk since it can be extended to be as large as necessary + (up to system limitations). + + 5. If the request size meets the mmap threshold and the + system supports mmap, and there are few enough currently + allocated mmapped regions, and a call to mmap succeeds, + the request is allocated via direct memory mapping. + + 6. Otherwise, the top of memory is extended by + obtaining more space from the system (normally using sbrk, + but definable to anything else via the MORECORE macro). + Memory is gathered from the system (in system page-sized + units) in a way that allows chunks obtained across different + sbrk calls to be consolidated, but does not require + contiguous memory. Thus, it should be safe to intersperse + mallocs with other sbrk calls. + + All allocations are made from the the `lowest' part of any found + chunk. (The implementation invariant is that prev_inuse is + always true of any allocated chunk; i.e., that each allocated + chunk borders either a previously allocated and still in-use chunk, + or the base of its memory arena.) + +*/ + +#if __STD_C +Void_t *mALLOc(size_t bytes) +#else +Void_t *mALLOc(bytes) +size_t bytes; +#endif +{ + mchunkptr victim; /* inspected/selected chunk */ + INTERNAL_SIZE_T victim_size; /* its size */ + int idx; /* index for bin traversal */ + mbinptr bin; /* associated bin */ + mchunkptr remainder; /* remainder from a split */ + long remainder_size; /* its size */ + int remainder_index; /* its bin index */ + unsigned long block; /* block traverser bit */ + int startidx; /* first bin of a traversed block */ + mchunkptr fwd; /* misc temp for linking */ + mchunkptr bck; /* misc temp for linking */ + mbinptr q; /* misc temp */ + + INTERNAL_SIZE_T nb; + + if ((long)bytes < 0) + return NULL; + + nb = request2size(bytes); /* padded request size; */ + + /* Check for exact match in a bin */ + + if (is_small_request(nb)) { /* Faster version for small requests */ + idx = smallbin_index(nb); + + /* No traversal or size check necessary for small bins. */ + + q = bin_at(idx); + victim = last(q); + + /* Also scan the next one, since it would have a remainder < MINSIZE */ + if (victim == q) { + q = next_bin(q); + victim = last(q); + } + if (victim != q) { + victim_size = chunksize(victim); + unlink(victim, bck, fwd); + set_inuse_bit_at_offset(victim, victim_size); + check_malloced_chunk(victim, nb); + return chunk2mem(victim); + } + + idx += 2; /* Set for bin scan below. We've already scanned 2 bins. */ + + } else { + idx = bin_index(nb); + bin = bin_at(idx); + + for (victim = last(bin); victim != bin; victim = victim->bk) { + victim_size = chunksize(victim); + remainder_size = victim_size - nb; + + if (remainder_size >= (long)MINSIZE) { /* too big */ + --idx; /* adjust to rescan below after checking last remainder */ + break; + } + + else if (remainder_size >= 0) { /* exact fit */ + unlink(victim, bck, fwd); + set_inuse_bit_at_offset(victim, victim_size); + check_malloced_chunk(victim, nb); + return chunk2mem(victim); + } + } + + ++idx; + + } + + /* Try to use the last split-off remainder */ + + if ((victim = last_remainder->fd) != last_remainder) { + victim_size = chunksize(victim); + remainder_size = victim_size - nb; + + if (remainder_size >= (long)MINSIZE) { /* re-split */ + remainder = chunk_at_offset(victim, nb); + set_head(victim, nb | PREV_INUSE); + link_last_remainder(remainder); + set_head(remainder, remainder_size | PREV_INUSE); + set_foot(remainder, remainder_size); + check_malloced_chunk(victim, nb); + return chunk2mem(victim); + } + + clear_last_remainder; + + if (remainder_size >= 0) { /* exhaust */ + set_inuse_bit_at_offset(victim, victim_size); + check_malloced_chunk(victim, nb); + return chunk2mem(victim); + } + + /* Else place in bin */ + + frontlink(victim, victim_size, remainder_index, bck, fwd); + } + + /* + If there are any possibly nonempty big-enough blocks, + search for best fitting chunk by scanning bins in blockwidth units. + */ + + if ((block = idx2binblock(idx)) <= binblocks) { + + /* Get to the first marked block */ + + if ((block & binblocks) == 0) { + /* force to an even block boundary */ + idx = (idx & ~(BINBLOCKWIDTH - 1)) + BINBLOCKWIDTH; + block <<= 1; + while ((block & binblocks) == 0) { + idx += BINBLOCKWIDTH; + block <<= 1; + } + } + + /* For each possibly nonempty block ... */ + for (;;) { + startidx = idx; /* (track incomplete blocks) */ + q = bin = bin_at(idx); + + /* For each bin in this block ... */ + do { + /* Find and use first big enough chunk ... */ + + for (victim = last(bin); victim != bin; + victim = victim->bk) { + victim_size = chunksize(victim); + remainder_size = victim_size - nb; + + if (remainder_size >= (long)MINSIZE) { /* split */ + remainder = + chunk_at_offset(victim, nb); + set_head(victim, + nb | PREV_INUSE); + unlink(victim, bck, fwd); + link_last_remainder(remainder); + set_head(remainder, + remainder_size | + PREV_INUSE); + set_foot(remainder, + remainder_size); + check_malloced_chunk(victim, + nb); + return chunk2mem(victim); + } + + else if (remainder_size >= 0) { /* take */ + set_inuse_bit_at_offset(victim, + victim_size); + unlink(victim, bck, fwd); + check_malloced_chunk(victim, + nb); + return chunk2mem(victim); + } + + } + + bin = next_bin(bin); + + } while ((++idx & (BINBLOCKWIDTH - 1)) != 0); + + /* Clear out the block bit. */ + + do { /* Possibly backtrack to try to clear a partial block */ + if ((startidx & (BINBLOCKWIDTH - 1)) == 0) { + binblocks &= ~block; + break; + } + --startidx; + q = prev_bin(q); + } while (first(q) == q); + + /* Get to the next possibly nonempty block */ + + if ((block <<= 1) <= binblocks && (block != 0)) { + while ((block & binblocks) == 0) { + idx += BINBLOCKWIDTH; + block <<= 1; + } + } else + break; + } + } + + /* Try to use top chunk */ + + /* Require that there be a remainder, ensuring top always exists */ + if ((remainder_size = chunksize(top) - nb) < (long)MINSIZE) { + +#if HAVE_MMAP + /* If big and would otherwise need to extend, try to use mmap instead */ + if ((unsigned long)nb >= (unsigned long)mmap_threshold && + (victim = mmap_chunk(nb)) != 0) + return chunk2mem(victim); +#endif + + /* Try to extend */ + malloc_extend_top(nb); + if ((remainder_size = chunksize(top) - nb) < (long)MINSIZE) + return NULL; /* propagate failure */ + } + + victim = top; + set_head(victim, nb | PREV_INUSE); + top = chunk_at_offset(victim, nb); + set_head(top, remainder_size | PREV_INUSE); + check_malloced_chunk(victim, nb); + return chunk2mem(victim); + +} + +/* + + free() algorithm : + + cases: + + 1. free(0) has no effect. + + 2. If the chunk was allocated via mmap, it is release via munmap(). + + 3. If a returned chunk borders the current high end of memory, + it is consolidated into the top, and if the total unused + topmost memory exceeds the trim threshold, malloc_trim is + called. + + 4. Other chunks are consolidated as they arrive, and + placed in corresponding bins. (This includes the case of + consolidating with the current `last_remainder'). + +*/ + +#if __STD_C +void fREe(Void_t *mem) +#else +void fREe(mem) +Void_t *mem; +#endif +{ + mchunkptr p; /* chunk corresponding to mem */ + INTERNAL_SIZE_T hd; /* its head field */ + INTERNAL_SIZE_T sz; /* its size */ + int idx; /* its bin index */ + mchunkptr next; /* next contiguous chunk */ + INTERNAL_SIZE_T nextsz; /* its size */ + INTERNAL_SIZE_T prevsz; /* size of previous contiguous chunk */ + mchunkptr bck; /* misc temp for linking */ + mchunkptr fwd; /* misc temp for linking */ + int islr; /* track whether merging with last_remainder */ + + if (mem == NULL) /* free(0) has no effect */ + return; + + p = mem2chunk(mem); + hd = p->size; + +#if HAVE_MMAP + if (hd & IS_MMAPPED) { /* release mmapped memory. */ + munmap_chunk(p); + return; + } +#endif + + check_inuse_chunk(p); + + sz = hd & ~PREV_INUSE; + next = chunk_at_offset(p, sz); + nextsz = chunksize(next); + + if (next == top) { /* merge with top */ + sz += nextsz; + + if (!(hd & PREV_INUSE)) { /* consolidate backward */ + prevsz = p->prev_size; + p = chunk_at_offset(p, -((long)prevsz)); + sz += prevsz; + unlink(p, bck, fwd); + } + + set_head(p, sz | PREV_INUSE); + top = p; + if ((unsigned long)(sz) >= (unsigned long)trim_threshold) + malloc_trim(top_pad); + return; + } + + set_head(next, nextsz); /* clear inuse bit */ + + islr = 0; + + if (!(hd & PREV_INUSE)) { /* consolidate backward */ + prevsz = p->prev_size; + p = chunk_at_offset(p, -((long)prevsz)); + sz += prevsz; + + if (p->fd == last_remainder) /* keep as last_remainder */ + islr = 1; + else + unlink(p, bck, fwd); + } + + if (!(inuse_bit_at_offset(next, nextsz))) { /* consolidate forward */ + sz += nextsz; + + if (!islr && next->fd == last_remainder) { /* re-insert last_remainder */ + islr = 1; + link_last_remainder(p); + } else + unlink(next, bck, fwd); + } + + set_head(p, sz | PREV_INUSE); + set_foot(p, sz); + if (!islr) + frontlink(p, sz, idx, bck, fwd); +} + +/* + + Realloc algorithm: + + Chunks that were obtained via mmap cannot be extended or shrunk + unless HAVE_MREMAP is defined, in which case mremap is used. + Otherwise, if their reallocation is for additional space, they are + copied. If for less, they are just left alone. + + Otherwise, if the reallocation is for additional space, and the + chunk can be extended, it is, else a malloc-copy-free sequence is + taken. There are several different ways that a chunk could be + extended. All are tried: + + * Extending forward into following adjacent free chunk. + * Shifting backwards, joining preceding adjacent space + * Both shifting backwards and extending forward. + * Extending into newly sbrked space + + Unless the #define REALLOC_ZERO_BYTES_FREES is set, realloc with a + size argument of zero (re)allocates a minimum-sized chunk. + + If the reallocation is for less space, and the new request is for + a `small' (<512 bytes) size, then the newly unused space is lopped + off and freed. + + The old unix realloc convention of allowing the last-free'd chunk + to be used as an argument to realloc is no longer supported. + I don't know of any programs still relying on this feature, + and allowing it would also allow too many other incorrect + usages of realloc to be sensible. + + +*/ + +#if __STD_C +Void_t *rEALLOc(Void_t *oldmem, size_t bytes) +#else +Void_t *rEALLOc(oldmem, bytes) +Void_t *oldmem; +size_t bytes; +#endif +{ + INTERNAL_SIZE_T nb; /* padded request size */ + + mchunkptr oldp; /* chunk corresponding to oldmem */ + INTERNAL_SIZE_T oldsize; /* its size */ + + mchunkptr newp; /* chunk to return */ + INTERNAL_SIZE_T newsize; /* its size */ + Void_t *newmem; /* corresponding user mem */ + + mchunkptr next; /* next contiguous chunk after oldp */ + INTERNAL_SIZE_T nextsize; /* its size */ + + mchunkptr prev; /* previous contiguous chunk before oldp */ + INTERNAL_SIZE_T prevsize; /* its size */ + + mchunkptr remainder; /* holds split off extra space from newp */ + INTERNAL_SIZE_T remainder_size; /* its size */ + + mchunkptr bck; /* misc temp for linking */ + mchunkptr fwd; /* misc temp for linking */ + +#ifdef REALLOC_ZERO_BYTES_FREES + if (bytes == 0) { + fREe(oldmem); + return 0; + } +#endif + + if ((long)bytes < 0) + return NULL; + + /* realloc of null is supposed to be same as malloc */ + if (oldmem == NULL) + return mALLOc(bytes); + + newp = oldp = mem2chunk(oldmem); + newsize = oldsize = chunksize(oldp); + + nb = request2size(bytes); + +#if HAVE_MMAP + if (chunk_is_mmapped(oldp)) { +#if HAVE_MREMAP + newp = mremap_chunk(oldp, nb); + if (newp) + return chunk2mem(newp); +#endif + /* Note the extra SIZE_SZ overhead. */ + if (oldsize - SIZE_SZ >= nb) + return oldmem; /* do nothing */ + /* Must alloc, copy, free. */ + newmem = mALLOc(bytes); + if (newmem == 0) + return 0; /* propagate failure */ + MALLOC_COPY(newmem, oldmem, oldsize - 2 * SIZE_SZ); + munmap_chunk(oldp); + return newmem; + } +#endif + + check_inuse_chunk(oldp); + + if ((long)(oldsize) < (long)(nb)) { + + /* Try expanding forward */ + + next = chunk_at_offset(oldp, oldsize); + if (next == top || !inuse(next)) { + nextsize = chunksize(next); + + /* Forward into top only if a remainder */ + if (next == top) { + if ((long)(nextsize + newsize) >= + (long)(nb + MINSIZE)) { + newsize += nextsize; + top = chunk_at_offset(oldp, nb); + set_head(top, + (newsize - nb) | PREV_INUSE); + set_head_size(oldp, nb); + return chunk2mem(oldp); + } + } + + /* Forward into next chunk */ + else if (((long)(nextsize + newsize) >= (long)(nb))) { + unlink(next, bck, fwd); + newsize += nextsize; + goto split; + } + } else { + next = NULL; + nextsize = 0; + } + + /* Try shifting backwards. */ + + if (!prev_inuse(oldp)) { + prev = prev_chunk(oldp); + prevsize = chunksize(prev); + + /* try forward + backward first to save a later consolidation */ + + if (next != NULL) { + /* into top */ + if (next == top) { + if ((long) + (nextsize + prevsize + newsize) >= + (long)(nb + MINSIZE)) { + unlink(prev, bck, fwd); + newp = prev; + newsize += prevsize + nextsize; + newmem = chunk2mem(newp); + MALLOC_COPY(newmem, oldmem, + oldsize - SIZE_SZ); + top = chunk_at_offset(newp, nb); + set_head(top, + (newsize - + nb) | PREV_INUSE); + set_head_size(newp, nb); + return newmem; + } + } + + /* into next chunk */ + else if (((long)(nextsize + prevsize + newsize) + >= (long)(nb))) { + unlink(next, bck, fwd); + unlink(prev, bck, fwd); + newp = prev; + newsize += nextsize + prevsize; + newmem = chunk2mem(newp); + MALLOC_COPY(newmem, oldmem, + oldsize - SIZE_SZ); + goto split; + } + } + + /* backward only */ + if (prev != NULL + && (long)(prevsize + newsize) >= (long)nb) { + unlink(prev, bck, fwd); + newp = prev; + newsize += prevsize; + newmem = chunk2mem(newp); + MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ); + goto split; + } + } + + /* Must allocate */ + + newmem = mALLOc(bytes); + + if (newmem == NULL) /* propagate failure */ + return NULL; + + /* Avoid copy if newp is next chunk after oldp. */ + /* (This can only happen when new chunk is sbrk'ed.) */ + + if ((newp = mem2chunk(newmem)) == next_chunk(oldp)) { + newsize += chunksize(newp); + newp = oldp; + goto split; + } + + /* Otherwise copy, free, and exit */ + MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ); + fREe(oldmem); + return newmem; + } + +split: /* split off extra room in old or expanded chunk */ + + if (newsize - nb >= MINSIZE) { /* split off remainder */ + remainder = chunk_at_offset(newp, nb); + remainder_size = newsize - nb; + set_head_size(newp, nb); + set_head(remainder, remainder_size | PREV_INUSE); + set_inuse_bit_at_offset(remainder, remainder_size); + fREe(chunk2mem(remainder)); /* let free() deal with it */ + } else { + set_head_size(newp, newsize); + set_inuse_bit_at_offset(newp, newsize); + } + + check_inuse_chunk(newp); + return chunk2mem(newp); +} + +/* + + memalign algorithm: + + memalign requests more than enough space from malloc, finds a spot + within that chunk that meets the alignment request, and then + possibly frees the leading and trailing space. + + The alignment argument must be a power of two. This property is not + checked by memalign, so misuse may result in random runtime errors. + + 8-byte alignment is guaranteed by normal malloc calls, so don't + bother calling memalign with an argument of 8 or less. + + Overreliance on memalign is a sure way to fragment space. + +*/ + +#if __STD_C +Void_t *mEMALIGn(size_t alignment, size_t bytes) +#else +Void_t *mEMALIGn(alignment, bytes) +size_t alignment; +size_t bytes; +#endif +{ + INTERNAL_SIZE_T nb; /* padded request size */ + char *m; /* memory returned by malloc call */ + mchunkptr p; /* corresponding chunk */ + char *brk; /* alignment point within p */ + mchunkptr newp; /* chunk to return */ + INTERNAL_SIZE_T newsize; /* its size */ + INTERNAL_SIZE_T leadsize; /* leading space befor alignment point */ + mchunkptr remainder; /* spare room at end to split off */ + long remainder_size; /* its size */ + + if ((long)bytes < 0) + return NULL; + + /* If need less alignment than we give anyway, just relay to malloc */ + + if (alignment <= MALLOC_ALIGNMENT) + return mALLOc(bytes); + + /* Otherwise, ensure that it is at least a minimum chunk size */ + + if (alignment < MINSIZE) + alignment = MINSIZE; + + /* Call malloc with worst case padding to hit alignment. */ + + nb = request2size(bytes); + m = (char *)(mALLOc(nb + alignment + MINSIZE)); + + if (m == NULL) + return NULL; /* propagate failure */ + + p = mem2chunk(m); + + if ((((unsigned long)(m)) % alignment) == 0) { /* aligned */ +#if HAVE_MMAP + if (chunk_is_mmapped(p)) + return chunk2mem(p); /* nothing more to do */ +#endif + } else { /* misaligned */ + + /* + Find an aligned spot inside chunk. + Since we need to give back leading space in a chunk of at + least MINSIZE, if the first calculation places us at + a spot with less than MINSIZE leader, we can move to the + next aligned spot -- we've allocated enough total room so that + this is always possible. + */ + + brk = + (char *)mem2chunk(((unsigned long)(m + alignment - 1)) & + -((signed)alignment)); + if ((long)(brk - (char *)(p)) < (long)MINSIZE) + brk = brk + alignment; + + newp = (mchunkptr) brk; + leadsize = brk - (char *)(p); + newsize = chunksize(p) - leadsize; + +#if HAVE_MMAP + if (chunk_is_mmapped(p)) { + newp->prev_size = p->prev_size + leadsize; + set_head(newp, newsize | IS_MMAPPED); + return chunk2mem(newp); + } +#endif + + /* give back leader, use the rest */ + + set_head(newp, newsize | PREV_INUSE); + set_inuse_bit_at_offset(newp, newsize); + set_head_size(p, leadsize); + fREe(chunk2mem(p)); + p = newp; + + assert(newsize >= nb + && (((unsigned long)(chunk2mem(p))) % alignment) == 0); + } + + /* Also give back spare room at the end */ + + remainder_size = chunksize(p) - nb; + + if (remainder_size >= (long)MINSIZE) { + remainder = chunk_at_offset(p, nb); + set_head(remainder, remainder_size | PREV_INUSE); + set_head_size(p, nb); + fREe(chunk2mem(remainder)); + } + + check_inuse_chunk(p); + return chunk2mem(p); + +} + +/* + valloc just invokes memalign with alignment argument equal + to the page size of the system (or as near to this as can + be figured out from all the includes/defines above.) +*/ + +#if __STD_C +Void_t *vALLOc(size_t bytes) +#else +Void_t *vALLOc(bytes) +size_t bytes; +#endif +{ + return mEMALIGn(malloc_getpagesize, bytes); +} + +/* + pvalloc just invokes valloc for the nearest pagesize + that will accommodate request +*/ + +#if __STD_C +Void_t *pvALLOc(size_t bytes) +#else +Void_t *pvALLOc(bytes) +size_t bytes; +#endif +{ + size_t pagesize = malloc_getpagesize; + return mEMALIGn(pagesize, (bytes + pagesize - 1) & ~(pagesize - 1)); +} + +/* + + calloc calls malloc, then zeroes out the allocated chunk. + +*/ + +#if __STD_C +Void_t *cALLOc(size_t n, size_t elem_size) +#else +Void_t *cALLOc(n, elem_size) +size_t n; +size_t elem_size; +#endif +{ + mchunkptr p; + INTERNAL_SIZE_T csz; + + INTERNAL_SIZE_T sz = n * elem_size; + + /* check if expand_top called, in which case don't need to clear */ +#if MORECORE_CLEARS + mchunkptr oldtop = top; + INTERNAL_SIZE_T oldtopsize = chunksize(top); +#endif + Void_t *mem = mALLOc(sz); + + if ((long)n < 0) + return NULL; + + if (mem == NULL) + return NULL; + else { + p = mem2chunk(mem); + + /* Two optional cases in which clearing not necessary */ + +#if HAVE_MMAP + if (chunk_is_mmapped(p)) + return mem; +#endif + + csz = chunksize(p); + +#if MORECORE_CLEARS + if (p == oldtop && csz > oldtopsize) { + /* clear only the bytes from non-freshly-sbrked memory */ + csz = oldtopsize; + } +#endif + + MALLOC_ZERO(mem, csz - SIZE_SZ); + return mem; + } +} + +/* + + cfree just calls free. It is needed/defined on some systems + that pair it with calloc, presumably for odd historical reasons. + +*/ + +#if !defined(INTERNAL_LINUX_C_LIB) || !defined(__ELF__) +#if __STD_C +void cfree(Void_t *mem) +#else +void cfree(mem) +Void_t *mem; +#endif +{ + fREe(mem); +} +#endif + +/* + + Malloc_trim gives memory back to the system (via negative + arguments to sbrk) if there is unused memory at the `high' end of + the malloc pool. You can call this after freeing large blocks of + memory to potentially reduce the system-level memory requirements + of a program. However, it cannot guarantee to reduce memory. Under + some allocation patterns, some large free blocks of memory will be + locked between two used chunks, so they cannot be given back to + the system. + + The `pad' argument to malloc_trim represents the amount of free + trailing space to leave untrimmed. If this argument is zero, + only the minimum amount of memory to maintain internal data + structures will be left (one page or less). Non-zero arguments + can be supplied to maintain enough trailing space to service + future expected allocations without having to re-obtain memory + from the system. + + Malloc_trim returns 1 if it actually released any memory, else 0. + +*/ + +#if __STD_C +int malloc_trim(size_t pad) +#else +int malloc_trim(pad) +size_t pad; +#endif +{ + long top_size; /* Amount of top-most memory */ + long extra; /* Amount to release */ + char *current_brk; /* address returned by pre-check sbrk call */ + char *new_brk; /* address returned by negative sbrk call */ + + unsigned long pagesz = malloc_getpagesize; + + top_size = chunksize(top); + extra = + ((top_size - pad - MINSIZE + (pagesz - 1)) / pagesz - 1) * pagesz; + + if (extra < (long)pagesz) /* Not enough memory to release */ + return 0; + + else { + /* Test to make sure no one else called sbrk */ + current_brk = (char *)(MORECORE(0)); + if (current_brk != (char *)(top) + top_size) + return 0; /* Apparently we don't own memory; must fail */ + + else { + new_brk = (char *)(MORECORE(-extra)); + + if (new_brk == (char *)(MORECORE_FAILURE)) { /* sbrk failed? */ + /* Try to figure out what we have */ + current_brk = (char *)(MORECORE(0)); + top_size = current_brk - (char *)top; + if (top_size >= (long)MINSIZE) { /* if not, we are very very dead! */ + sbrked_mem = current_brk - sbrk_base; + set_head(top, top_size | PREV_INUSE); + } + check_chunk(top); + return 0; + } + + else { + /* Success. Adjust top accordingly. */ + set_head(top, (top_size - extra) | PREV_INUSE); + sbrked_mem -= extra; + check_chunk(top); + return 1; + } + } + } +} + +/* + malloc_usable_size: + + This routine tells you how many bytes you can actually use in an + allocated chunk, which may be more than you requested (although + often not). You can use this many bytes without worrying about + overwriting other allocated objects. Not a particularly great + programming practice, but still sometimes useful. + +*/ + +#if __STD_C +size_t malloc_usable_size(Void_t *mem) +#else +size_t malloc_usable_size(mem) +Void_t *mem; +#endif +{ + mchunkptr p; + if (mem == NULL) + return 0; + else { + p = mem2chunk(mem); + if (!chunk_is_mmapped(p)) { + if (!inuse(p)) + return 0; + check_inuse_chunk(p); + return chunksize(p) - SIZE_SZ; + } + return chunksize(p) - 2 * SIZE_SZ; + } +} + +/* Utility to update current_mallinfo for malloc_stats and mallinfo() */ + +static void malloc_update_mallinfo(void) +{ + int i; + mbinptr b; + mchunkptr p; +#if DEBUG + mchunkptr q; +#endif + + INTERNAL_SIZE_T avail = chunksize(top); + int navail = ((long)(avail) >= (long)MINSIZE) ? 1 : 0; + + for (i = 1; i < NAV; ++i) { + b = bin_at(i); + for (p = last(b); p != b; p = p->bk) { +#if DEBUG + check_free_chunk(p); + for (q = next_chunk(p); + q < top && inuse(q) + && (long)(chunksize(q)) >= (long)MINSIZE; + q = next_chunk(q)) + check_inuse_chunk(q); +#endif + avail += chunksize(p); + navail++; + } + } + + current_mallinfo.ordblks = navail; + current_mallinfo.uordblks = sbrked_mem - avail; + current_mallinfo.fordblks = avail; + current_mallinfo.hblks = n_mmaps; + current_mallinfo.hblkhd = mmapped_mem; + current_mallinfo.keepcost = chunksize(top); + +} + +/* + + malloc_stats: + + Prints on stderr the amount of space obtain from the system (both + via sbrk and mmap), the maximum amount (which may be more than + current if malloc_trim and/or munmap got called), the maximum + number of simultaneous mmap regions used, and the current number + of bytes allocated via malloc (or realloc, etc) but not yet + freed. (Note that this is the number of bytes allocated, not the + number requested. It will be larger than the number requested + because of alignment and bookkeeping overhead.) + +*/ + +void malloc_stats(void) +{ + malloc_update_mallinfo(); + fprintf(stderr, "max system bytes = %10u\n", + (unsigned int)(max_total_mem)); + fprintf(stderr, "system bytes = %10u\n", + (unsigned int)(sbrked_mem + mmapped_mem)); + fprintf(stderr, "in use bytes = %10u\n", + (unsigned int)(current_mallinfo.uordblks + mmapped_mem)); +#if HAVE_MMAP + fprintf(stderr, "max mmap regions = %10u\n", (unsigned int)max_n_mmaps); +#endif +} + +/* + mallinfo returns a copy of updated current mallinfo. +*/ + +struct mallinfo *mALLINFo(void) +{ + malloc_update_mallinfo(); + return ¤t_mallinfo; +} + +/* + mallopt: + + mallopt is the general SVID/XPG interface to tunable parameters. + The format is to provide a (parameter-number, parameter-value) pair. + mallopt then sets the corresponding parameter to the argument + value if it can (i.e., so long as the value is meaningful), + and returns 1 if successful else 0. + + See descriptions of tunable parameters above. + +*/ + +#if __STD_C +int mALLOPt(int param_number, int value) +#else +int mALLOPt(param_number, value) +int param_number; +int value; +#endif +{ + switch (param_number) { + case M_TRIM_THRESHOLD: + trim_threshold = value; + return 1; + case M_TOP_PAD: + top_pad = value; + return 1; + case M_MMAP_THRESHOLD: + mmap_threshold = value; + return 1; + case M_MMAP_MAX: +#if HAVE_MMAP + n_mmaps_max = value; + return 1; +#else + if (value != 0) + return 0; + else + n_mmaps_max = value; + return 1; +#endif + + default: + return 0; + } +} + +/* + +History: + + V2.6.6 Sun Dec 5 07:42:19 1999 Doug Lea (dl at gee) + * return null for negative arguments + * Added Several WIN32 cleanups from Martin C. Fong + * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h' + (e.g. WIN32 platforms) + * Cleanup up header file inclusion for WIN32 platforms + * Cleanup code to avoid Microsoft Visual C++ compiler complaints + * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing + memory allocation routines + * Set 'malloc_getpagesize' for WIN32 platforms (needs more work) + * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to + usage of 'assert' in non-WIN32 code + * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to + avoid infinite loop + * Always call 'fREe()' rather than 'free()' + + V2.6.5 Wed Jun 17 15:57:31 1998 Doug Lea (dl at gee) + * Fixed ordering problem with boundary-stamping + + V2.6.3 Sun May 19 08:17:58 1996 Doug Lea (dl at gee) + * Added pvalloc, as recommended by H.J. Liu + * Added 64bit pointer support mainly from Wolfram Gloger + * Added anonymously donated WIN32 sbrk emulation + * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen + * malloc_extend_top: fix mask error that caused wastage after + foreign sbrks + * Add linux mremap support code from HJ Liu + + V2.6.2 Tue Dec 5 06:52:55 1995 Doug Lea (dl at gee) + * Integrated most documentation with the code. + * Add support for mmap, with help from + Wolfram Gloger (Gloger@lrz.uni-muenchen.de). + * Use last_remainder in more cases. + * Pack bins using idea from colin@nyx10.cs.du.edu + * Use ordered bins instead of best-fit threshhold + * Eliminate block-local decls to simplify tracing and debugging. + * Support another case of realloc via move into top + * Fix error occuring when initial sbrk_base not word-aligned. + * Rely on page size for units instead of SBRK_UNIT to + avoid surprises about sbrk alignment conventions. + * Add mallinfo, mallopt. Thanks to Raymond Nijssen + (raymond@es.ele.tue.nl) for the suggestion. + * Add `pad' argument to malloc_trim and top_pad mallopt parameter. + * More precautions for cases where other routines call sbrk, + courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de). + * Added macros etc., allowing use in linux libc from + H.J. Lu (hjl@gnu.ai.mit.edu) + * Inverted this history list + + V2.6.1 Sat Dec 2 14:10:57 1995 Doug Lea (dl at gee) + * Re-tuned and fixed to behave more nicely with V2.6.0 changes. + * Removed all preallocation code since under current scheme + the work required to undo bad preallocations exceeds + the work saved in good cases for most test programs. + * No longer use return list or unconsolidated bins since + no scheme using them consistently outperforms those that don't + given above changes. + * Use best fit for very large chunks to prevent some worst-cases. + * Added some support for debugging + + V2.6.0 Sat Nov 4 07:05:23 1995 Doug Lea (dl at gee) + * Removed footers when chunks are in use. Thanks to + Paul Wilson (wilson@cs.texas.edu) for the suggestion. + + V2.5.4 Wed Nov 1 07:54:51 1995 Doug Lea (dl at gee) + * Added malloc_trim, with help from Wolfram Gloger + (wmglo@Dent.MED.Uni-Muenchen.DE). + + V2.5.3 Tue Apr 26 10:16:01 1994 Doug Lea (dl at g) + + V2.5.2 Tue Apr 5 16:20:40 1994 Doug Lea (dl at g) + * realloc: try to expand in both directions + * malloc: swap order of clean-bin strategy; + * realloc: only conditionally expand backwards + * Try not to scavenge used bins + * Use bin counts as a guide to preallocation + * Occasionally bin return list chunks in first scan + * Add a few optimizations from colin@nyx10.cs.du.edu + + V2.5.1 Sat Aug 14 15:40:43 1993 Doug Lea (dl at g) + * faster bin computation & slightly different binning + * merged all consolidations to one part of malloc proper + (eliminating old malloc_find_space & malloc_clean_bin) + * Scan 2 returns chunks (not just 1) + * Propagate failure in realloc if malloc returns 0 + * Add stuff to allow compilation on non-ANSI compilers + from kpv@research.att.com + + V2.5 Sat Aug 7 07:41:59 1993 Doug Lea (dl at g.oswego.edu) + * removed potential for odd address access in prev_chunk + * removed dependency on getpagesize.h + * misc cosmetics and a bit more internal documentation + * anticosmetics: mangled names in macros to evade debugger strangeness + * tested on sparc, hp-700, dec-mips, rs6000 + with gcc & native cc (hp, dec only) allowing + Detlefs & Zorn comparison study (in SIGPLAN Notices.) + + Trial version Fri Aug 28 13:14:29 1992 Doug Lea (dl at g.oswego.edu) + * Based loosely on libg++-1.2X malloc. (It retains some of the overall + structure of old version, but most details differ.) + +*/ diff --git a/lib/libutils/isoc/dlmalloc.h b/lib/libutils/isoc/dlmalloc.h new file mode 100644 index 00000000000..26b7b62d888 --- /dev/null +++ b/lib/libutils/isoc/dlmalloc.h @@ -0,0 +1,941 @@ +#ifndef DLMALLOC_H +#define DLMALLOC_H + +#define USE_DL_PREFIX /* see details below */ +#define HAVE_USR_INCLUDE_MALLOC_H 0 +#define NO_STDIO_H_REQUIRED +#define malloc_getpagesize 4096 +#define USE_MEMCPY 1 +#define HAVE_MMAP 0 +#ifndef DEBUG +#define DEBUG 0 /* dlmalloc needs a defined DEBUG */ +#endif + +/* + A version of malloc/free/realloc written by Doug Lea and released to the + public domain. Send questions/comments/complaints/performance data + to dl@cs.oswego.edu + +* VERSION 2.6.6 Sun Mar 5 19:10:03 2000 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at + ftp://g.oswego.edu/pub/misc/malloc.c + Check before installing! + +* Why use this malloc? + + This is not the fastest, most space-conserving, most portable, or + most tunable malloc ever written. However it is among the fastest + while also being among the most space-conserving, portable and tunable. + Consistent balance across these factors results in a good general-purpose + allocator. For a high-level description, see + http://g.oswego.edu/dl/html/malloc.html + +* Synopsis of public routines + + (Much fuller descriptions are contained in the program documentation below.) + + malloc(size_t n); + Return a pointer to a newly allocated chunk of at least n bytes, or null + if no space is available. + free(Void_t* p); + Release the chunk of memory pointed to by p, or no effect if p is null. + realloc(Void_t* p, size_t n); + Return a pointer to a chunk of size n that contains the same data + as does chunk p up to the minimum of (n, p's size) bytes, or null + if no space is available. The returned pointer may or may not be + the same as p. If p is null, equivalent to malloc. Unless the + #define REALLOC_ZERO_BYTES_FREES below is set, realloc with a + size argument of zero (re)allocates a minimum-sized chunk. + memalign(size_t alignment, size_t n); + Return a pointer to a newly allocated chunk of n bytes, aligned + in accord with the alignment argument, which must be a power of + two. + valloc(size_t n); + Equivalent to memalign(pagesize, n), where pagesize is the page + size of the system (or as near to this as can be figured out from + all the includes/defines below.) + pvalloc(size_t n); + Equivalent to valloc(minimum-page-that-holds(n)), that is, + round up n to nearest pagesize. + calloc(size_t unit, size_t quantity); + Returns a pointer to quantity * unit bytes, with all locations + set to zero. + cfree(Void_t* p); + Equivalent to free(p). + malloc_trim(size_t pad); + Release all but pad bytes of freed top-most memory back + to the system. Return 1 if successful, else 0. + malloc_usable_size(Void_t* p); + Report the number usable allocated bytes associated with allocated + chunk p. This may or may not report more bytes than were requested, + due to alignment and minimum size constraints. + malloc_stats(); + Prints brief summary statistics on stderr. + mallinfo() + Returns (by copy) a struct containing various summary statistics. + mallopt(int parameter_number, int parameter_value) + Changes one of the tunable parameters described below. Returns + 1 if successful in changing the parameter, else 0. + +* Vital statistics: + + Alignment: 8-byte + 8 byte alignment is currently hardwired into the design. This + seems to suffice for all current machines and C compilers. + + Assumed pointer representation: 4 or 8 bytes + Code for 8-byte pointers is untested by me but has worked + reliably by Wolfram Gloger, who contributed most of the + changes supporting this. + + Assumed size_t representation: 4 or 8 bytes + Note that size_t is allowed to be 4 bytes even if pointers are 8. + + Minimum overhead per allocated chunk: 4 or 8 bytes + Each malloced chunk has a hidden overhead of 4 bytes holding size + and status information. + + Minimum allocated size: 4-byte ptrs: 16 bytes (including 4 overhead) + 8-byte ptrs: 24/32 bytes (including, 4/8 overhead) + + When a chunk is freed, 12 (for 4byte ptrs) or 20 (for 8 byte + ptrs but 4 byte size) or 24 (for 8/8) additional bytes are + needed; 4 (8) for a trailing size field + and 8 (16) bytes for free list pointers. Thus, the minimum + allocatable size is 16/24/32 bytes. + + Even a request for zero bytes (i.e., malloc(0)) returns a + pointer to something of the minimum allocatable size. + + Maximum allocated size: 4-byte size_t: 2^31 - 8 bytes + 8-byte size_t: 2^63 - 16 bytes + + It is assumed that (possibly signed) size_t bit values suffice to + represent chunk sizes. `Possibly signed' is due to the fact + that `size_t' may be defined on a system as either a signed or + an unsigned type. To be conservative, values that would appear + as negative numbers are avoided. + Requests for sizes with a negative sign bit when the request + size is treaded as a long will return null. + + Maximum overhead wastage per allocated chunk: normally 15 bytes + + Alignnment demands, plus the minimum allocatable size restriction + make the normal worst-case wastage 15 bytes (i.e., up to 15 + more bytes will be allocated than were requested in malloc), with + two exceptions: + 1. Because requests for zero bytes allocate non-zero space, + the worst case wastage for a request of zero bytes is 24 bytes. + 2. For requests >= mmap_threshold that are serviced via + mmap(), the worst case wastage is 8 bytes plus the remainder + from a system page (the minimal mmap unit); typically 4096 bytes. + +* Limitations + + Here are some features that are NOT currently supported + + * No user-definable hooks for callbacks and the like. + * No automated mechanism for fully checking that all accesses + to malloced memory stay within their bounds. + * No support for compaction. + +* Synopsis of compile-time options: + + People have reported using previous versions of this malloc on all + versions of Unix, sometimes by tweaking some of the defines + below. It has been tested most extensively on Solaris and + Linux. It is also reported to work on WIN32 platforms. + People have also reported adapting this malloc for use in + stand-alone embedded systems. + + The implementation is in straight, hand-tuned ANSI C. Among other + consequences, it uses a lot of macros. Because of this, to be at + all usable, this code should be compiled using an optimizing compiler + (for example gcc -O2) that can simplify expressions and control + paths. + + __STD_C (default: derived from C compiler defines) + Nonzero if using ANSI-standard C compiler, a C++ compiler, or + a C compiler sufficiently close to ANSI to get away with it. + DEBUG (default: NOT defined) + Define to enable debugging. Adds fairly extensive assertion-based + checking to help track down memory errors, but noticeably slows down + execution. + REALLOC_ZERO_BYTES_FREES (default: NOT defined) + Define this if you think that realloc(p, 0) should be equivalent + to free(p). Otherwise, since malloc returns a unique pointer for + malloc(0), so does realloc(p, 0). + HAVE_MEMCPY (default: defined) + Define if you are not otherwise using ANSI STD C, but still + have memcpy and memset in your C library and want to use them. + Otherwise, simple internal versions are supplied. + USE_MEMCPY (default: 1 if HAVE_MEMCPY is defined, 0 otherwise) + Define as 1 if you want the C library versions of memset and + memcpy called in realloc and calloc (otherwise macro versions are used). + At least on some platforms, the simple macro versions usually + outperform libc versions. + HAVE_MMAP (default: defined as 1) + Define to non-zero to optionally make malloc() use mmap() to + allocate very large blocks. + HAVE_MREMAP (default: defined as 0 unless Linux libc set) + Define to non-zero to optionally make realloc() use mremap() to + reallocate very large blocks. + malloc_getpagesize (default: derived from system #includes) + Either a constant or routine call returning the system page size. + HAVE_USR_INCLUDE_MALLOC_H (default: NOT defined) + Optionally define if you are on a system with a /usr/include/malloc.h + that declares struct mallinfo. It is not at all necessary to + define this even if you do, but will ensure consistency. + INTERNAL_SIZE_T (default: size_t) + Define to a 32-bit type (probably `unsigned int') if you are on a + 64-bit machine, yet do not want or need to allow malloc requests of + greater than 2^31 to be handled. This saves space, especially for + very small chunks. + INTERNAL_LINUX_C_LIB (default: NOT defined) + Defined only when compiled as part of Linux libc. + Also note that there is some odd internal name-mangling via defines + (for example, internally, `malloc' is named `mALLOc') needed + when compiling in this case. These look funny but don't otherwise + affect anything. + WIN32 (default: undefined) + Define this on MS win (95, nt) platforms to compile in sbrk emulation. + LACKS_UNISTD_H (default: undefined if not WIN32) + Define this if your system does not have a . + LACKS_SYS_PARAM_H (default: undefined if not WIN32) + Define this if your system does not have a . + MORECORE (default: sbrk) + The name of the routine to call to obtain more memory from the system. + MORECORE_FAILURE (default: -1) + The value returned upon failure of MORECORE. + MORECORE_CLEARS (default 1) + True (1) if the routine mapped to MORECORE zeroes out memory (which + holds for sbrk). + DEFAULT_TRIM_THRESHOLD + DEFAULT_TOP_PAD + DEFAULT_MMAP_THRESHOLD + DEFAULT_MMAP_MAX + Default values of tunable parameters (described in detail below) + controlling interaction with host system routines (sbrk, mmap, etc). + These values may also be changed dynamically via mallopt(). The + preset defaults are those that give best performance for typical + programs/systems. + USE_DL_PREFIX (default: undefined) + Prefix all public routines with the string 'dl'. Useful to + quickly avoid procedure declaration conflicts and linker symbol + conflicts with existing memory allocation routines. + + +*/ + +/* + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ST BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Preliminaries */ + +#ifndef __STD_C +#ifdef __STDC__ +#define __STD_C 1 +#else +#if __cplusplus +#define __STD_C 1 +#else +#define __STD_C 0 +#endif /* __cplusplus */ +#endif /* __STDC__ */ +#endif /* __STD_C */ + +#ifndef Void_t +#if (__STD_C || defined(WIN32)) +#define Void_t void +#else +#define Void_t char +#endif +#endif /* Void_t */ + +#if __STD_C +#include /* for size_t */ +#else +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef NO_STDIO_H_REQUIRED +#include /* needed for malloc_stats */ +#endif + +/* + Compile-time options +*/ + +/* + Debugging: + + Because freed chunks may be overwritten with link fields, this + malloc will often die when freed memory is overwritten by user + programs. This can be very effective (albeit in an annoying way) + in helping track down dangling pointers. + + If you compile with -DDEBUG, a number of assertion checks are + enabled that will catch more memory errors. You probably won't be + able to make much sense of the actual assertion errors, but they + should help you locate incorrectly overwritten memory. The + checking is fairly extensive, and will slow down execution + noticeably. Calling malloc_stats or mallinfo with DEBUG set will + attempt to check every non-mmapped allocated and free chunk in the + course of computing the summmaries. (By nature, mmapped regions + cannot be checked very much automatically.) + + Setting DEBUG may also be helpful if you are trying to modify + this code. The assertions in the check routines spell out in more + detail the assumptions and invariants underlying the algorithms. + +*/ + +/*#if (defined DEBUG) && (DEBUG != 0) */ +#include +/*#else */ +/*#define assert(x) ((void)0) */ +/*#endif */ + +/* + INTERNAL_SIZE_T is the word-size used for internal bookkeeping + of chunk sizes. On a 64-bit machine, you can reduce malloc + overhead by defining INTERNAL_SIZE_T to be a 32 bit `unsigned int' + at the expense of not being able to handle requests greater than + 2^31. This limitation is hardly ever a concern; you are encouraged + to set this. However, the default version is the same as size_t. +*/ + +#ifndef INTERNAL_SIZE_T +#define INTERNAL_SIZE_T size_t +#endif + +/* + REALLOC_ZERO_BYTES_FREES should be set if a call to + realloc with zero bytes should be the same as a call to free. + Some people think it should. Otherwise, since this malloc + returns a unique pointer for malloc(0), so does realloc(p, 0). +*/ + +/* #define REALLOC_ZERO_BYTES_FREES */ + +/* + WIN32 causes an emulation of sbrk to be compiled in + mmap-based options are not currently supported in WIN32. +*/ + +/* #define WIN32 */ +#ifdef WIN32 +#define MORECORE wsbrk +#define HAVE_MMAP 0 + +#define LACKS_UNISTD_H +#define LACKS_SYS_PARAM_H + +/* + Include 'windows.h' to get the necessary declarations for the + Microsoft Visual C++ data structures and routines used in the 'sbrk' + emulation. + + Define WIN32_LEAN_AND_MEAN so that only the essential Microsoft + Visual C++ header files are included. +*/ +#define WIN32_LEAN_AND_MEAN +#include +#endif + +/* + HAVE_MEMCPY should be defined if you are not otherwise using + ANSI STD C, but still have memcpy and memset in your C library + and want to use them in calloc and realloc. Otherwise simple + macro versions are defined here. + + USE_MEMCPY should be defined as 1 if you actually want to + have memset and memcpy called. People report that the macro + versions are often enough faster than libc versions on many + systems that it is better to use them. + +*/ + +#define HAVE_MEMCPY + +#ifndef USE_MEMCPY +#ifdef HAVE_MEMCPY +#define USE_MEMCPY 1 +#else +#define USE_MEMCPY 0 +#endif +#endif + +#if (__STD_C || defined(HAVE_MEMCPY)) + +#if __STD_C + void *memset(void *, int, size_t); + void *memcpy(void *, const void *, size_t); +#else +#ifdef WIN32 +/* On Win32 platforms, 'memset()' and 'memcpy()' are already declared in */ +/* 'windows.h' */ +#else + Void_t *memset(); + Void_t *memcpy(); +#endif +#endif +#endif + +#if USE_MEMCPY + +/* The following macros are only invoked with (2n+1)-multiples of + INTERNAL_SIZE_T units, with a positive integer n. This is exploited + for fast inline execution when n is small. */ + +#define MALLOC_ZERO(charp, nbytes) \ +do { \ + INTERNAL_SIZE_T mzsz = (nbytes); \ + if(mzsz <= 9*sizeof(mzsz)) { \ + INTERNAL_SIZE_T* mz = (INTERNAL_SIZE_T*) (charp); \ + if(mzsz >= 5*sizeof(mzsz)) { *mz++ = 0; \ + *mz++ = 0; \ + if(mzsz >= 7*sizeof(mzsz)) { *mz++ = 0; \ + *mz++ = 0; \ + if(mzsz >= 9*sizeof(mzsz)) { *mz++ = 0; \ + *mz++ = 0; }}} \ + *mz++ = 0; \ + *mz++ = 0; \ + *mz = 0; \ + } else memset((charp), 0, mzsz); \ +} while(0) + +#define MALLOC_COPY(dest,src,nbytes) \ +do { \ + INTERNAL_SIZE_T mcsz = (nbytes); \ + if(mcsz <= 9*sizeof(mcsz)) { \ + INTERNAL_SIZE_T* mcsrc = (INTERNAL_SIZE_T*) (src); \ + INTERNAL_SIZE_T* mcdst = (INTERNAL_SIZE_T*) (dest); \ + if(mcsz >= 5*sizeof(mcsz)) { *mcdst++ = *mcsrc++; \ + *mcdst++ = *mcsrc++; \ + if(mcsz >= 7*sizeof(mcsz)) { *mcdst++ = *mcsrc++; \ + *mcdst++ = *mcsrc++; \ + if(mcsz >= 9*sizeof(mcsz)) { *mcdst++ = *mcsrc++; \ + *mcdst++ = *mcsrc++; }}} \ + *mcdst++ = *mcsrc++; \ + *mcdst++ = *mcsrc++; \ + *mcdst = *mcsrc ; \ + } else memcpy(dest, src, mcsz); \ +} while(0) + +#else /* !USE_MEMCPY */ + +/* Use Duff's device for good zeroing/copying performance. */ + +#define MALLOC_ZERO(charp, nbytes) \ +do { \ + INTERNAL_SIZE_T* mzp = (INTERNAL_SIZE_T*)(charp); \ + long mctmp = (nbytes)/sizeof(INTERNAL_SIZE_T), mcn; \ + if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp %= 8; } \ + switch (mctmp) { \ + case 0: for(;;) { *mzp++ = 0; \ + case 7: *mzp++ = 0; \ + case 6: *mzp++ = 0; \ + case 5: *mzp++ = 0; \ + case 4: *mzp++ = 0; \ + case 3: *mzp++ = 0; \ + case 2: *mzp++ = 0; \ + case 1: *mzp++ = 0; if(mcn <= 0) break; mcn--; } \ + } \ +} while(0) + +#define MALLOC_COPY(dest,src,nbytes) \ +do { \ + INTERNAL_SIZE_T* mcsrc = (INTERNAL_SIZE_T*) src; \ + INTERNAL_SIZE_T* mcdst = (INTERNAL_SIZE_T*) dest; \ + long mctmp = (nbytes)/sizeof(INTERNAL_SIZE_T), mcn; \ + if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp %= 8; } \ + switch (mctmp) { \ + case 0: for(;;) { *mcdst++ = *mcsrc++; \ + case 7: *mcdst++ = *mcsrc++; \ + case 6: *mcdst++ = *mcsrc++; \ + case 5: *mcdst++ = *mcsrc++; \ + case 4: *mcdst++ = *mcsrc++; \ + case 3: *mcdst++ = *mcsrc++; \ + case 2: *mcdst++ = *mcsrc++; \ + case 1: *mcdst++ = *mcsrc++; if(mcn <= 0) break; mcn--; } \ + } \ +} while(0) + +#endif + +/* + Define HAVE_MMAP to optionally make malloc() use mmap() to + allocate very large blocks. These will be returned to the + operating system immediately after a free(). +*/ + +#ifndef HAVE_MMAP +#define HAVE_MMAP 1 +#endif + +/* + Define HAVE_MREMAP to make realloc() use mremap() to re-allocate + large blocks. This is currently only possible on Linux with + kernel versions newer than 1.3.77. +*/ + +#ifndef HAVE_MREMAP +#ifdef INTERNAL_LINUX_C_LIB +#define HAVE_MREMAP 1 +#else +#define HAVE_MREMAP 0 +#endif +#endif + +#if HAVE_MMAP + +#include +#include +#include + +#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) +#define MAP_ANONYMOUS MAP_ANON +#endif + +#endif /* HAVE_MMAP */ + +/* + Access to system page size. To the extent possible, this malloc + manages memory from the system in page-size units. + + The following mechanics for getpagesize were adapted from + bsd/gnu getpagesize.h +*/ + +#ifndef LACKS_UNISTD_H +#include +#endif + +#ifndef malloc_getpagesize +#ifdef _SC_PAGESIZE /* some SVR4 systems omit an underscore */ +#ifndef _SC_PAGE_SIZE +#define _SC_PAGE_SIZE _SC_PAGESIZE +#endif +#endif +#ifdef _SC_PAGE_SIZE +#define malloc_getpagesize sysconf(_SC_PAGE_SIZE) +#else +#if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE) + extern size_t getpagesize(); +#define malloc_getpagesize getpagesize() +#else +#ifdef WIN32 +#define malloc_getpagesize (4096) /* TBD: Use 'GetSystemInfo' instead */ +#else +#ifndef LACKS_SYS_PARAM_H +#include +#endif +#ifdef EXEC_PAGESIZE +#define malloc_getpagesize EXEC_PAGESIZE +#else +#ifdef NBPG +#ifndef CLSIZE +#define malloc_getpagesize NBPG +#else +#define malloc_getpagesize (NBPG * CLSIZE) +#endif +#else +#ifdef NBPC +#define malloc_getpagesize NBPC +#else +#ifdef PAGESIZE +#define malloc_getpagesize PAGESIZE +#else +#define malloc_getpagesize (4096) /* just guess */ +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif + +/* + + This version of malloc supports the standard SVID/XPG mallinfo + routine that returns a struct containing the same kind of + information you can get from malloc_stats. It should work on + any SVID/XPG compliant system that has a /usr/include/malloc.h + defining struct mallinfo. (If you'd like to install such a thing + yourself, cut out the preliminary declarations as described above + and below and save them in a malloc.h file. But there's no + compelling reason to bother to do this.) + + The main declaration needed is the mallinfo struct that is returned + (by-copy) by mallinfo(). The SVID/XPG malloinfo struct contains a + bunch of fields, most of which are not even meaningful in this + version of malloc. Some of these fields are are instead filled by + mallinfo() with other numbers that might possibly be of interest. + + HAVE_USR_INCLUDE_MALLOC_H should be set if you have a + /usr/include/malloc.h file that includes a declaration of struct + mallinfo. If so, it is included; else an SVID2/XPG2 compliant + version is declared below. These must be precisely the same for + mallinfo() to work. + +*/ + +/* #define HAVE_USR_INCLUDE_MALLOC_H */ + +#if HAVE_USR_INCLUDE_MALLOC_H +#include "/usr/include/malloc.h" +#else + +/* SVID2/XPG mallinfo structure */ + + struct mallinfo { + int arena; /* total space allocated from system */ + int ordblks; /* number of non-inuse chunks */ + int smblks; /* unused -- always zero */ + int hblks; /* number of mmapped regions */ + int hblkhd; /* total space in mmapped regions */ + int usmblks; /* unused -- always zero */ + int fsmblks; /* unused -- always zero */ + int uordblks; /* total allocated space */ + int fordblks; /* total non-inuse space */ + int keepcost; /* top-most, releasable (via malloc_trim) space */ + }; + +/* SVID2/XPG mallopt options */ + +#define M_MXFAST 1 /* UNUSED in this malloc */ +#define M_NLBLKS 2 /* UNUSED in this malloc */ +#define M_GRAIN 3 /* UNUSED in this malloc */ +#define M_KEEP 4 /* UNUSED in this malloc */ + +#endif + +/* mallopt options that actually do something */ + +#define M_TRIM_THRESHOLD -1 +#define M_TOP_PAD -2 +#define M_MMAP_THRESHOLD -3 +#define M_MMAP_MAX -4 + +#ifndef DEFAULT_TRIM_THRESHOLD +#define DEFAULT_TRIM_THRESHOLD (128 * 1024) +#endif + +/* + M_TRIM_THRESHOLD is the maximum amount of unused top-most memory + to keep before releasing via malloc_trim in free(). + + Automatic trimming is mainly useful in long-lived programs. + Because trimming via sbrk can be slow on some systems, and can + sometimes be wasteful (in cases where programs immediately + afterward allocate more large chunks) the value should be high + enough so that your overall system performance would improve by + releasing. + + The trim threshold and the mmap control parameters (see below) + can be traded off with one another. Trimming and mmapping are + two different ways of releasing unused memory back to the + system. Between these two, it is often possible to keep + system-level demands of a long-lived program down to a bare + minimum. For example, in one test suite of sessions measuring + the XF86 X server on Linux, using a trim threshold of 128K and a + mmap threshold of 192K led to near-minimal long term resource + consumption. + + If you are using this malloc in a long-lived program, it should + pay to experiment with these values. As a rough guide, you + might set to a value close to the average size of a process + (program) running on your system. Releasing this much memory + would allow such a process to run in memory. Generally, it's + worth it to tune for trimming rather tham memory mapping when a + program undergoes phases where several large chunks are + allocated and released in ways that can reuse each other's + storage, perhaps mixed with phases where there are no such + chunks at all. And in well-behaved long-lived programs, + controlling release of large blocks via trimming versus mapping + is usually faster. + + However, in most programs, these parameters serve mainly as + protection against the system-level effects of carrying around + massive amounts of unneeded memory. Since frequent calls to + sbrk, mmap, and munmap otherwise degrade performance, the default + parameters are set to relatively high values that serve only as + safeguards. + + The default trim value is high enough to cause trimming only in + fairly extreme (by current memory consumption standards) cases. + It must be greater than page size to have any useful effect. To + disable trimming completely, you can set to (unsigned long)(-1); + + +*/ + +#ifndef DEFAULT_TOP_PAD +#define DEFAULT_TOP_PAD (0) +#endif + +/* + M_TOP_PAD is the amount of extra `padding' space to allocate or + retain whenever sbrk is called. It is used in two ways internally: + + * When sbrk is called to extend the top of the arena to satisfy + a new malloc request, this much padding is added to the sbrk + request. + + * When malloc_trim is called automatically from free(), + it is used as the `pad' argument. + + In both cases, the actual amount of padding is rounded + so that the end of the arena is always a system page boundary. + + The main reason for using padding is to avoid calling sbrk so + often. Having even a small pad greatly reduces the likelihood + that nearly every malloc request during program start-up (or + after trimming) will invoke sbrk, which needlessly wastes + time. + + Automatic rounding-up to page-size units is normally sufficient + to avoid measurable overhead, so the default is 0. However, in + systems where sbrk is relatively slow, it can pay to increase + this value, at the expense of carrying around more memory than + the program needs. + +*/ + +#ifndef DEFAULT_MMAP_THRESHOLD +#define DEFAULT_MMAP_THRESHOLD (128 * 1024) +#endif + +/* + + M_MMAP_THRESHOLD is the request size threshold for using mmap() + to service a request. Requests of at least this size that cannot + be allocated using already-existing space will be serviced via mmap. + (If enough normal freed space already exists it is used instead.) + + Using mmap segregates relatively large chunks of memory so that + they can be individually obtained and released from the host + system. A request serviced through mmap is never reused by any + other request (at least not directly; the system may just so + happen to remap successive requests to the same locations). + + Segregating space in this way has the benefit that mmapped space + can ALWAYS be individually released back to the system, which + helps keep the system level memory demands of a long-lived + program low. Mapped memory can never become `locked' between + other chunks, as can happen with normally allocated chunks, which + menas that even trimming via malloc_trim would not release them. + + However, it has the disadvantages that: + + 1. The space cannot be reclaimed, consolidated, and then + used to service later requests, as happens with normal chunks. + 2. It can lead to more wastage because of mmap page alignment + requirements + 3. It causes malloc performance to be more dependent on host + system memory management support routines which may vary in + implementation quality and may impose arbitrary + limitations. Generally, servicing a request via normal + malloc steps is faster than going through a system's mmap. + + All together, these considerations should lead you to use mmap + only for relatively large requests. + + +*/ + +#ifndef DEFAULT_MMAP_MAX +#if HAVE_MMAP +#define DEFAULT_MMAP_MAX (64) +#else +#define DEFAULT_MMAP_MAX (0) +#endif +#endif + +/* + M_MMAP_MAX is the maximum number of requests to simultaneously + service using mmap. This parameter exists because: + + 1. Some systems have a limited number of internal tables for + use by mmap. + 2. In most systems, overreliance on mmap can degrade overall + performance. + 3. If a program allocates many large regions, it is probably + better off using normal sbrk-based allocation routines that + can reclaim and reallocate normal heap memory. Using a + small value allows transition into this mode after the + first few allocations. + + Setting to 0 disables all use of mmap. If HAVE_MMAP is not set, + the default value is 0, and attempts to set it to non-zero values + in mallopt will fail. +*/ + +/* + USE_DL_PREFIX will prefix all public routines with the string 'dl'. + Useful to quickly avoid procedure declaration conflicts and linker + symbol conflicts with existing memory allocation routines. + +*/ + +/* #define USE_DL_PREFIX */ + +/* + + Special defines for linux libc + + Except when compiled using these special defines for Linux libc + using weak aliases, this malloc is NOT designed to work in + multithreaded applications. No semaphores or other concurrency + control are provided to ensure that multiple malloc or free calls + don't run at the same time, which could be disasterous. A single + semaphore could be used across malloc, realloc, and free (which is + essentially the effect of the linux weak alias approach). It would + be hard to obtain finer granularity. + +*/ + +#ifdef INTERNAL_LINUX_C_LIB + +#if __STD_C + + Void_t *__default_morecore_init(ptrdiff_t); + Void_t *(*__morecore) (ptrdiff_t) = __default_morecore_init; + +#else + + Void_t *__default_morecore_init(); + Void_t *(*__morecore) () = __default_morecore_init; + +#endif + +#define MORECORE (*__morecore) +#define MORECORE_FAILURE 0 +#define MORECORE_CLEARS 1 + +#else /* INTERNAL_LINUX_C_LIB */ + +#if __STD_C + extern Void_t *sbrk(ptrdiff_t); +#else + extern Void_t *sbrk(); +#endif + +#ifndef MORECORE +#define MORECORE sbrk +#endif + +#ifndef MORECORE_FAILURE +#define MORECORE_FAILURE -1 +#endif + +#ifndef MORECORE_CLEARS +#define MORECORE_CLEARS 1 +#endif + +#endif /* INTERNAL_LINUX_C_LIB */ + +#if defined(INTERNAL_LINUX_C_LIB) && defined(__ELF__) + +#define cALLOc __libc_calloc +#define fREe __libc_free +#define mALLOc __libc_malloc +#define mEMALIGn __libc_memalign +#define rEALLOc __libc_realloc +#define vALLOc __libc_valloc +#define pvALLOc __libc_pvalloc +#define mALLINFo __libc_mallinfo +#define mALLOPt __libc_mallopt + +#pragma weak calloc = __libc_calloc +#pragma weak free = __libc_free +#pragma weak cfree = __libc_free +#pragma weak malloc = __libc_malloc +#pragma weak memalign = __libc_memalign +#pragma weak realloc = __libc_realloc +#pragma weak valloc = __libc_valloc +#pragma weak pvalloc = __libc_pvalloc +#pragma weak mallinfo = __libc_mallinfo +#pragma weak mallopt = __libc_mallopt + +#else + +#ifdef USE_DL_PREFIX +#define cALLOc dlcalloc +#define fREe dlfree +#define mALLOc dlmalloc +#define mEMALIGn dlmemalign +#define rEALLOc dlrealloc +#define vALLOc dlvalloc +#define pvALLOc dlpvalloc +#define mALLINFo dlmallinfo +#define mALLOPt dlmallopt +#else /* USE_DL_PREFIX */ +#define cALLOc calloc +#define fREe free +#define mALLOc malloc +#define mEMALIGn memalign +#define rEALLOc realloc +#define vALLOc valloc +#define pvALLOc pvalloc +#define mALLINFo mallinfo +#define mALLOPt mallopt +#endif /* USE_DL_PREFIX */ + +#endif + +/* Public routines */ + +#if __STD_C + + Void_t *mALLOc(size_t); + void fREe(Void_t *); + Void_t *rEALLOc(Void_t *, size_t); + Void_t *mEMALIGn(size_t, size_t); + Void_t *vALLOc(size_t); + Void_t *pvALLOc(size_t); + Void_t *cALLOc(size_t, size_t); + void cfree(Void_t *); + int malloc_trim(size_t); + size_t malloc_usable_size(Void_t *); + void malloc_stats(void); + int mALLOPt(int, int); + struct mallinfo *mALLINFo(void); +#else + Void_t *mALLOc(); + void fREe(); + Void_t *rEALLOc(); + Void_t *mEMALIGn(); + Void_t *vALLOc(); + Void_t *pvALLOc(); + Void_t *cALLOc(); + void cfree(); + int malloc_trim(); + size_t malloc_usable_size(); + void malloc_stats(); + int mALLOPt(); + struct mallinfo *mALLINFo(); +#endif + +#ifdef __cplusplus +}; /* end of extern "C" */ +#endif + +#endif /* DLMALLOC_H */ diff --git a/lib/libutils/isoc/include/assert.h b/lib/libutils/isoc/include/assert.h new file mode 100644 index 00000000000..060ef2f7a3a --- /dev/null +++ b/lib/libutils/isoc/include/assert.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef ASSERT_H +#define ASSERT_H + +void _assert_break(void); +void _assert_log(const char *expr, const char *file, int line); + +#define assert(expr) \ + do { \ + if (!(expr)) { \ + _assert_log(#expr, __FILE__, __LINE__); \ + _assert_break(); \ + } \ + } while (0) + +#endif diff --git a/lib/libutils/isoc/include/ctype.h b/lib/libutils/isoc/include/ctype.h new file mode 100644 index 00000000000..ea4df10d9bd --- /dev/null +++ b/lib/libutils/isoc/include/ctype.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef CTYPE_H +#define CTYPE_H + +#endif /*CTYPE_H*/ diff --git a/lib/libutils/isoc/include/inttypes.h b/lib/libutils/isoc/include/inttypes.h new file mode 100644 index 00000000000..77464d5e2bf --- /dev/null +++ b/lib/libutils/isoc/include/inttypes.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef INTTYPES_H +#define INTTYPES_H + +#include + +#define __PRI64_PREFIX "ll" +#define __PRIPTR_PREFIX "l" + +#define PRId8 "d" +#define PRId16 "d" +#define PRId32 "d" +#define PRId64 __PRI64_PREFIX "d" +#define PRIdPTR __PRIPTR_PREFIX "d" + +#define PRIi8 "i" +#define PRIi16 "i" +#define PRIi32 "i" +#define PRIi64 __PRI64_PREFIX "i" +#define PRIiPTR __PRIPTR_PREFIX "i" + +#define PRIo8 "o" +#define PRIo16 "o" +#define PRIo32 "o" +#define PRIo64 __PRI64_PREFIX "o" +#define PRIoPTR __PRIPTR_PREFIX "o" + +#define PRIu8 "u" +#define PRIu16 "u" +#define PRIu32 "u" +#define PRIu64 __PRI64_PREFIX "u" +#define PRIuPTR __PRIPTR_PREFIX "u" + +#define PRIx8 "x" +#define PRIx16 "x" +#define PRIx32 "x" +#define PRIx64 __PRI64_PREFIX "x" +#define PRIxPTR __PRIPTR_PREFIX "x" + +#define PRIX8 "X" +#define PRIX16 "X" +#define PRIX32 "X" +#define PRIX64 __PRI64_PREFIX "X" +#define PRIXPTR __PRIPTR_PREFIX "X" + +#endif /*INTTYPES_H*/ diff --git a/lib/libutils/isoc/include/limits.h b/lib/libutils/isoc/include/limits.h new file mode 100644 index 00000000000..fe49e6504d1 --- /dev/null +++ b/lib/libutils/isoc/include/limits.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef LIMITS_H +#define LIMITS_H + +#define CHAR_BIT __CHAR_BIT__ + +#ifdef __CHAR_UNSIGNED__ +#define CHAR_MAX UCHAR_MAX +#define CHAR_MIN 0 +#else +#define CHAR_MAX SCHAR_MAX +#define CHAR_MIN SCHAR_MIN +#endif + +#define INT_MAX __INT_MAX__ +#define INT_MIN (-INT_MAX - 1) + +#define LONG_MAX __LONG_MAX__ +#define LONG_MIN (-LONG_MAX - 1L) + +#define LLONG_MAX __LONG_LONG_MAX__ +#define LLONG_MIN (-LLONG_MAX - 1LL) + +#define MB_LEN_MAX 1 + +#define SCHAR_MAX __SCHAR_MAX__ +#define SCHAR_MIN (-SCHAR_MAX - 1) + +#define SHRT_MAX __SHRT_MAX__ +#define SHRT_MIN (-SHRT_MAX - 1) + +#if __SCHAR_MAX__ == __INT_MAX__ +#define UCHAR_MAX (SCHAR_MAX * 2U + 1U) +#else +#define UCHAR_MAX (SCHAR_MAX * 2 + 1) +#endif + +#if __SHRT_MAX__ == __INT_MAX__ +#define USHRT_MAX (SHRT_MAX * 2U + 1U) +#else +#define USHRT_MAX (SHRT_MAX * 2 + 1) +#endif + +#define UINT_MAX (INT_MAX * 2U + 1U) + +#define ULONG_MAX (LONG_MAX * 2UL + 1UL) +#define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL) + +#endif /* LIMITS_H */ diff --git a/lib/libutils/isoc/include/malloc.h b/lib/libutils/isoc/include/malloc.h new file mode 100644 index 00000000000..e9000ecd6eb --- /dev/null +++ b/lib/libutils/isoc/include/malloc.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef MALLOC_H +#define MALLOC_H + +#include + +enum mdbg_mode { + MDBG_MODE_STATIC, + MDBG_MODE_DYNAMIC +}; + +/* + * ENABLE_MDBG: malloc debug support + * + * When enabled, malloc, calloc, realloc and free are redirected from SLA + * to routines that trace memory callers (filename/line) and provide few other + * memory alloc debug features. calloc and realloc are routed to basic malloc. + * + * memalign and other standard mem alloc APIs are not handled by mdbg. + * + * If ENABLE_MDBG is not set, malloc.c acts as a wrapper to redirect std + * malloc apis to the apis of the embedded malloc library (SLA, dlmalloc,...). + */ +#ifdef ENABLE_MDBG + +/* define mdbg 'malloc' routine and redirect std apis to these. */ +void *mdbg_malloc(const char *fname, int lineno, unsigned nbytes); +void *mdbg_calloc(const char *fname, int lineno, unsigned nelem, + unsigned elsize); +#ifdef MDBG_REALLOC_ENABLED +void *mdbg_realloc(const char *fname, int lineno, void *ptr, unsigned size); +#endif + +void mdbg_free(void *fp); +void mdbg_dump(int bufdump); +enum mdbg_mode mdbg_set_mode(enum mdbg_mode mode); +void mdbg_check(void); + +/* Redefine standard memory allocator calls to use our routines instead. */ +#define free mdbg_free +#define malloc(x) mdbg_malloc(__FILE__, __LINE__, (x)) +#define calloc(n, e) mdbg_calloc(__FILE__, __LINE__, (n), (e)) +#define realloc(p, x) mdbg_realloc(__FILE__, __LINE__, (p), (x)) + +#else + +/* mdbg not enabled: simple define standard apis */ +void *calloc(size_t nmemb, size_t size); +void free(void *ptr); +void *malloc(size_t size); +void *realloc(void *ptr, size_t size); + +#define mdbg_check() do { } while (0) +#define mdbg_dump(x) do { } while (0) +static inline enum mdbg_mode mdbg_set_mode(enum mdbg_mode mode) +{ + return mode; +} + +#endif /* ENABLE_MDBG */ + +/* other standard malloc apis */ +void *memalign(size_t size, size_t a); +void *valloc(size_t size); +void *pvalloc(size_t size); + +/* entry point for malloc init in case some inits are required */ +void malloc_init(void *start, size_t size); + +#endif /* MALLOC_H */ diff --git a/lib/libutils/isoc/include/memory.h b/lib/libutils/isoc/include/memory.h new file mode 100644 index 00000000000..d4e298db08e --- /dev/null +++ b/lib/libutils/isoc/include/memory.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef MEMORY_H +#define MEMORY_H +#include + +#endif /*MEMORY_H*/ diff --git a/lib/libutils/isoc/include/signal.h b/lib/libutils/isoc/include/signal.h new file mode 100644 index 00000000000..6ee25186732 --- /dev/null +++ b/lib/libutils/isoc/include/signal.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef SIGNAL_H +#define SIGNAL_H + +#endif /*SIGNAL_H*/ diff --git a/lib/libutils/isoc/include/stdint.h b/lib/libutils/isoc/include/stdint.h new file mode 100644 index 00000000000..6d49f9dab65 --- /dev/null +++ b/lib/libutils/isoc/include/stdint.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file provides what C99 standard requires in + * 7.18 interger types + * with the exception of: + * o Minimum-width integer types + * o Fastest minimum-width integer types + * o Geatest-width integer types + */ + +#ifndef STDINT_H +#define STDINT_H +#define _STDINT_H + +/* 7.18.1.1 Exact-width interger types */ +#ifndef __int8_t_defined +# define __int8_t_defined +typedef signed char int8_t; +typedef short int int16_t; +typedef int int32_t; +__extension__ +typedef long long int int64_t; +#endif + +/* Unsigned. */ +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; +#ifndef __uint32_t_defined +typedef unsigned int uint32_t; +# define __uint32_t_defined +#endif +__extension__ +typedef unsigned long long int uint64_t; + +/* 7.18.1.4 Integer types capable of holding object pointers */ + +typedef int32_t intptr_t; +typedef uint32_t uintptr_t; + +typedef int32_t intmax_t; +typedef uint32_t uintmax_t; + +/* + * 7.18.2 Limits of specified-width integer types + */ + +/* 7.18.2.1 Limits of exact-width interger types */ + +#define INT8_MIN (-0x7f-1) +#define INT16_MIN (-0x7fff-1) +#define INT32_MIN (-0x7fffffff-1) +#define INT64_MIN (-0x7fffffffffffffffL-1) + +#define INT8_MAX 0x7f +#define INT16_MAX 0x7fff +#define INT32_MAX 0x7fffffff +#define INT64_MAX 0x7fffffffffffffffL + +#define UINT8_MAX 0xff +#define UINT16_MAX 0xffff +#define UINT32_MAX 0xffffffffU +#define UINT64_MAX 0xffffffffffffffffUL + +/* 7.18.2.4 Limits of integer types capable of holding object pointers */ + +#define INTPTR_MIN INT32_MIN +#define INTPTR_MAX INT32_MAX +#define UINTPTR_MAX UINT32_MAX + +#endif /* STDINT_H */ diff --git a/lib/libutils/isoc/include/stdio.h b/lib/libutils/isoc/include/stdio.h new file mode 100644 index 00000000000..1c0cea6867c --- /dev/null +++ b/lib/libutils/isoc/include/stdio.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef STDIO_H +#define STDIO_H + +#include +#include + +typedef struct _FILE FILE; + +int printf(const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 1, 2))); +int snprintf(char *str, size_t size, const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 3, 4))); +int vsnprintf (char *str, size_t size, const char *fmt, va_list ap) + __attribute__ ((__format__ (__printf__, 3, 0))); + +int puts(const char *str); + +#endif /*STDIO_H*/ diff --git a/lib/libutils/isoc/include/stdlib.h b/lib/libutils/isoc/include/stdlib.h new file mode 100644 index 00000000000..3e0c86ca068 --- /dev/null +++ b/lib/libutils/isoc/include/stdlib.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file provides what C99 standard requires for in + * 7.20.3 Memory management functions + */ + +#ifndef STDLIB_H +#define STDLIB_H + +#include +#include + +void +qsort(void *aa, size_t n, size_t es, int (*cmp)(const void *, const void *)); + +#endif /* STDLIB_H */ diff --git a/lib/libutils/isoc/include/string.h b/lib/libutils/isoc/include/string.h new file mode 100644 index 00000000000..baf51166083 --- /dev/null +++ b/lib/libutils/isoc/include/string.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file provides what C99 standard requires for + * for some functions + */ + +#ifndef STRING_H +#define STRING_H + +#include +#include + +void *memcpy(void *__restrict s1, const void *__restrict s2, size_t n); +void *memmove(void *s1, const void *s2, size_t n); +int memcmp(const void *s1, const void *s2, size_t n); +void *memset(void *s, int c, size_t n); + +int strcmp(const char *s1, const char *s2); +size_t strlen(const char *s); +size_t strnlen(const char *s, size_t n); +char *strdup(const char *s); +char *strndup(const char *s, size_t n); + +void *memchr(const void *buf, int c, size_t length); + +#endif /* STRING_H */ diff --git a/lib/libutils/isoc/include/sys/cdefs.h b/lib/libutils/isoc/include/sys/cdefs.h new file mode 100644 index 00000000000..79078690c11 --- /dev/null +++ b/lib/libutils/isoc/include/sys/cdefs.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef SYS_CDEFS_H +#define SYS_CDEFS_H + +/* + * GCC 2.95 provides `__restrict' as an extension to C90 to support the + * C99-specific `restrict' type qualifier. We happen to use `__restrict' as + * a way to define the `restrict' type qualifier without disturbing older + * software that is unaware of C99 keywords. + */ +#if !(__GNUC__ == 2 && __GNUC_MINOR__ == 95) +#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901 || defined(lint) +#define __restrict +#else +#define __restrict restrict +#endif +#endif + +#endif /*SYS_CDEFS_H*/ diff --git a/lib/libutils/isoc/include/sys/queue.h b/lib/libutils/isoc/include/sys/queue.h new file mode 100644 index 00000000000..920b3c020a2 --- /dev/null +++ b/lib/libutils/isoc/include/sys/queue.h @@ -0,0 +1,699 @@ +/* $NetBSD: queue.h,v 1.49.6.1 2008/11/20 03:22:38 snj Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + */ + +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +/*#include */ + +/* + * This file defines five types of data structures: singly-linked lists, + * lists, simple queues, tail queues, and circular queues. + * + * A singly-linked list is headed by a single forward pointer. The + * elements are singly linked for minimum space and pointer manipulation + * overhead at the expense of O(n) removal for arbitrary elements. New + * elements can be added to the list after an existing element or at the + * head of the list. Elements being removed from the head of the list + * should use the explicit macro for this purpose for optimum + * efficiency. A singly-linked list may only be traversed in the forward + * direction. Singly-linked lists are ideal for applications with large + * datasets and few or no removals or for implementing a LIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A simple queue is headed by a pair of pointers, one the head of the + * list and the other to the tail of the list. The elements are singly + * linked to save space, so elements can only be removed from the + * head of the list. New elements can be added to the list after + * an existing element, at the head of the list, or at the end of the + * list. A simple queue may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * A circle queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the list. + * A circle queue may be traversed in either direction, but has a more + * complex end of list detection. + * + * For details on the use of these macros, see the queue(3) manual page. + */ + +/* + * List definitions. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List functions. + */ +#if defined(_KERNEL) && defined(QUEUEDEBUG) +#define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field) \ + if ((head)->lh_first && \ + (head)->lh_first->field.le_prev != &(head)->lh_first) \ + panic("LIST_INSERT_HEAD %p %s:%d", (head), __FILE__, __LINE__); +#define QUEUEDEBUG_LIST_OP(elm, field) \ + if ((elm)->field.le_next && \ + (elm)->field.le_next->field.le_prev != \ + &(elm)->field.le_next) \ + panic("LIST_* forw %p %s:%d", (elm), __FILE__, __LINE__);\ + if (*(elm)->field.le_prev != (elm)) \ + panic("LIST_* back %p %s:%d", (elm), __FILE__, __LINE__); +#define QUEUEDEBUG_LIST_POSTREMOVE(elm, field) \ + (elm)->field.le_next = (void *)1L; \ + (elm)->field.le_prev = (void *)1L; +#else +#define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field) +#define QUEUEDEBUG_LIST_OP(elm, field) +#define QUEUEDEBUG_LIST_POSTREMOVE(elm, field) +#endif + +#define LIST_INIT(head) do { \ + (head)->lh_first = NULL; \ +} while (/* CONSTCOND */0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + QUEUEDEBUG_LIST_OP((listelm), field) \ + if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ + (listelm)->field.le_next->field.le_prev = \ + &(elm)->field.le_next; \ + (listelm)->field.le_next = (elm); \ + (elm)->field.le_prev = &(listelm)->field.le_next; \ +} while (/* CONSTCOND */0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + QUEUEDEBUG_LIST_OP((listelm), field) \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + (elm)->field.le_next = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &(elm)->field.le_next; \ +} while (/* CONSTCOND */0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + QUEUEDEBUG_LIST_INSERT_HEAD((head), (elm), field) \ + if (((elm)->field.le_next = (head)->lh_first) != NULL) \ + (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ + (head)->lh_first = (elm); \ + (elm)->field.le_prev = &(head)->lh_first; \ +} while (/* CONSTCOND */0) + +#define LIST_REMOVE(elm, field) do { \ + QUEUEDEBUG_LIST_OP((elm), field) \ + if ((elm)->field.le_next != NULL) \ + (elm)->field.le_next->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = (elm)->field.le_next; \ + QUEUEDEBUG_LIST_POSTREMOVE((elm), field) \ +} while (/* CONSTCOND */0) + +#define LIST_FOREACH(var, head, field) \ + for ((var) = ((head)->lh_first); \ + (var); \ + (var) = ((var)->field.le_next)) + +/* + * List access methods. + */ +#define LIST_EMPTY(head) ((head)->lh_first == NULL) +#define LIST_FIRST(head) ((head)->lh_first) +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +/* + * Singly-linked List definitions. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List functions. + */ +#define SLIST_INIT(head) do { \ + (head)->slh_first = NULL; \ +} while (/* CONSTCOND */0) + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + (elm)->field.sle_next = (slistelm)->field.sle_next; \ + (slistelm)->field.sle_next = (elm); \ +} while (/* CONSTCOND */0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.sle_next = (head)->slh_first; \ + (head)->slh_first = (elm); \ +} while (/* CONSTCOND */0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + (head)->slh_first = (head)->slh_first->field.sle_next; \ +} while (/* CONSTCOND */0) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + if ((head)->slh_first == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = (head)->slh_first; \ + while(curelm->field.sle_next != (elm)) \ + curelm = curelm->field.sle_next; \ + curelm->field.sle_next = \ + curelm->field.sle_next->field.sle_next; \ + } \ +} while (/* CONSTCOND */0) + +#define SLIST_REMOVE_AFTER(slistelm, field) do { \ + (slistelm)->field.sle_next = \ + SLIST_NEXT(SLIST_NEXT((slistelm), field), field); \ +} while (/* CONSTCOND */0) + +#define SLIST_FOREACH(var, head, field) \ + for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next) + +/* + * Singly-linked List access methods. + */ +#define SLIST_EMPTY(head) ((head)->slh_first == NULL) +#define SLIST_FIRST(head) ((head)->slh_first) +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +/* + * Singly-linked Tail queue declarations. + */ +#define STAILQ_HEAD(name, type) \ +struct name { \ + struct type *stqh_first; /* first element */ \ + struct type **stqh_last; /* addr of last next element */ \ +} + +#define STAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first } + +#define STAILQ_ENTRY(type) \ +struct { \ + struct type *stqe_next; /* next element */ \ +} + +/* + * Singly-linked Tail queue functions. + */ +#define STAILQ_INIT(head) do { \ + (head)->stqh_first = NULL; \ + (head)->stqh_last = &(head)->stqh_first; \ +} while (/* CONSTCOND */0) + +#define STAILQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \ + (head)->stqh_last = &(elm)->field.stqe_next; \ + (head)->stqh_first = (elm); \ +} while (/* CONSTCOND */0) + +#define STAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.stqe_next = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &(elm)->field.stqe_next; \ +} while (/* CONSTCOND */0) + +#define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\ + (head)->stqh_last = &(elm)->field.stqe_next; \ + (listelm)->field.stqe_next = (elm); \ +} while (/* CONSTCOND */0) + +#define STAILQ_REMOVE_HEAD(head, field) do { \ + if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \ + (head)->stqh_last = &(head)->stqh_first; \ +} while (/* CONSTCOND */0) + +#define STAILQ_REMOVE(head, elm, type, field) do { \ + if ((head)->stqh_first == (elm)) { \ + STAILQ_REMOVE_HEAD((head), field); \ + } else { \ + struct type *curelm = (head)->stqh_first; \ + while (curelm->field.stqe_next != (elm)) \ + curelm = curelm->field.stqe_next; \ + if ((curelm->field.stqe_next = \ + curelm->field.stqe_next->field.stqe_next) == NULL) \ + (head)->stqh_last = &(curelm)->field.stqe_next; \ + } \ +} while (/* CONSTCOND */0) + +#define STAILQ_FOREACH(var, head, field) \ + for ((var) = ((head)->stqh_first); \ + (var); \ + (var) = ((var)->field.stqe_next)) + +#define STAILQ_CONCAT(head1, head2) do { \ + if (!STAILQ_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_INIT((head2)); \ + } \ +} while (/* CONSTCOND */0) + +/* + * Singly-linked Tail queue access methods. + */ +#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) +#define STAILQ_FIRST(head) ((head)->stqh_first) +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) + +/* + * Simple queue definitions. + */ +#define SIMPLEQ_HEAD(name, type) \ +struct name { \ + struct type *sqh_first; /* first element */ \ + struct type **sqh_last; /* addr of last next element */ \ +} + +#define SIMPLEQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).sqh_first } + +#define SIMPLEQ_ENTRY(type) \ +struct { \ + struct type *sqe_next; /* next element */ \ +} + +/* + * Simple queue functions. + */ +#define SIMPLEQ_INIT(head) do { \ + (head)->sqh_first = NULL; \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (/* CONSTCOND */0) + +#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (head)->sqh_first = (elm); \ +} while (/* CONSTCOND */0) + +#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.sqe_next = NULL; \ + *(head)->sqh_last = (elm); \ + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (/* CONSTCOND */0) + +#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (listelm)->field.sqe_next = (elm); \ +} while (/* CONSTCOND */0) + +#define SIMPLEQ_REMOVE_HEAD(head, field) do { \ + if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (/* CONSTCOND */0) + +#define SIMPLEQ_REMOVE(head, elm, type, field) do { \ + if ((head)->sqh_first == (elm)) { \ + SIMPLEQ_REMOVE_HEAD((head), field); \ + } else { \ + struct type *curelm = (head)->sqh_first; \ + while (curelm->field.sqe_next != (elm)) \ + curelm = curelm->field.sqe_next; \ + if ((curelm->field.sqe_next = \ + curelm->field.sqe_next->field.sqe_next) == NULL) \ + (head)->sqh_last = &(curelm)->field.sqe_next; \ + } \ +} while (/* CONSTCOND */0) + +#define SIMPLEQ_FOREACH(var, head, field) \ + for ((var) = ((head)->sqh_first); \ + (var); \ + (var) = ((var)->field.sqe_next)) + +/* + * Simple queue access methods. + */ +#define SIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL) +#define SIMPLEQ_FIRST(head) ((head)->sqh_first) +#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) + +/* + * Tail queue definitions. + */ +#define _TAILQ_HEAD(name, type, qual) \ +struct name { \ + qual type *tqh_first; /* first element */ \ + qual type *qual *tqh_last; /* addr of last next element */ \ +} +#define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,) + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define _TAILQ_ENTRY(type, qual) \ +struct { \ + qual type *tqe_next; /* next element */ \ + qual type *qual *tqe_prev; /* address of previous next element */\ +} +#define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,) + +/* + * Tail queue functions. + */ +#if defined(_KERNEL) && defined(QUEUEDEBUG) +#define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field) \ + if ((head)->tqh_first && \ + (head)->tqh_first->field.tqe_prev != &(head)->tqh_first) \ + panic("TAILQ_INSERT_HEAD %p %s:%d", (head), __FILE__, __LINE__); +#define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field) \ + if (*(head)->tqh_last != NULL) \ + panic("TAILQ_INSERT_TAIL %p %s:%d", (head), __FILE__, __LINE__); +#define QUEUEDEBUG_TAILQ_OP(elm, field) \ + if ((elm)->field.tqe_next && \ + (elm)->field.tqe_next->field.tqe_prev != \ + &(elm)->field.tqe_next) \ + panic("TAILQ_* forw %p %s:%d", (elm), __FILE__, __LINE__);\ + if (*(elm)->field.tqe_prev != (elm)) \ + panic("TAILQ_* back %p %s:%d", (elm), __FILE__, __LINE__); +#define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field) \ + if ((elm)->field.tqe_next == NULL && \ + (head)->tqh_last != &(elm)->field.tqe_next) \ + panic("TAILQ_PREREMOVE head %p elm %p %s:%d", \ + (head), (elm), __FILE__, __LINE__); +#define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field) \ + (elm)->field.tqe_next = (void *)1L; \ + (elm)->field.tqe_prev = (void *)1L; +#else +#define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field) +#define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field) +#define QUEUEDEBUG_TAILQ_OP(elm, field) +#define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field) +#define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field) +#endif + +#define TAILQ_INIT(head) do { \ + (head)->tqh_first = NULL; \ + (head)->tqh_last = &(head)->tqh_first; \ +} while (/* CONSTCOND */0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + QUEUEDEBUG_TAILQ_INSERT_HEAD((head), (elm), field) \ + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ + (head)->tqh_first->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ +} while (/* CONSTCOND */0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + QUEUEDEBUG_TAILQ_INSERT_TAIL((head), (elm), field) \ + (elm)->field.tqe_next = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ +} while (/* CONSTCOND */0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + QUEUEDEBUG_TAILQ_OP((listelm), field) \ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (listelm)->field.tqe_next = (elm); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ +} while (/* CONSTCOND */0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + QUEUEDEBUG_TAILQ_OP((listelm), field) \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ +} while (/* CONSTCOND */0) + +#define TAILQ_REMOVE(head, elm, field) do { \ + QUEUEDEBUG_TAILQ_PREREMOVE((head), (elm), field) \ + QUEUEDEBUG_TAILQ_OP((elm), field) \ + if (((elm)->field.tqe_next) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ + QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \ +} while (/* CONSTCOND */0) + +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = ((head)->tqh_first); \ + (var); \ + (var) = ((var)->field.tqe_next)) + +#define TAILQ_FOREACH_SAFE(var, head, field, next) \ + for ((var) = ((head)->tqh_first); \ + (var) != NULL && ((next) = TAILQ_NEXT(var, field), 1); \ + (var) = (next)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \ + (var); \ + (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last))) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, prev) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var) && ((prev) = TAILQ_PREV((var), headname, field), 1);\ + (var) = (prev)) + +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + } \ +} while (/* CONSTCOND */0) + +/* + * Tail queue access methods. + */ +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) +#define TAILQ_FIRST(head) ((head)->tqh_first) +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + +/* + * Circular queue definitions. + */ +#if defined(_KERNEL) && defined(QUEUEDEBUG) +#define QUEUEDEBUG_CIRCLEQ_HEAD(head, field) \ + if ((head)->cqh_first != (void *)(head) && \ + (head)->cqh_first->field.cqe_prev != (void *)(head)) \ + panic("CIRCLEQ head forw %p %s:%d", (head), \ + __FILE__, __LINE__); \ + if ((head)->cqh_last != (void *)(head) && \ + (head)->cqh_last->field.cqe_next != (void *)(head)) \ + panic("CIRCLEQ head back %p %s:%d", (head), \ + __FILE__, __LINE__); +#define QUEUEDEBUG_CIRCLEQ_ELM(head, elm, field) \ + if ((elm)->field.cqe_next == (void *)(head)) { \ + if ((head)->cqh_last != (elm)) \ + panic("CIRCLEQ elm last %p %s:%d", (elm), \ + __FILE__, __LINE__); \ + } else { \ + if ((elm)->field.cqe_next->field.cqe_prev != (elm)) \ + panic("CIRCLEQ elm forw %p %s:%d", (elm), \ + __FILE__, __LINE__); \ + } \ + if ((elm)->field.cqe_prev == (void *)(head)) { \ + if ((head)->cqh_first != (elm)) \ + panic("CIRCLEQ elm first %p %s:%d", (elm), \ + __FILE__, __LINE__); \ + } else { \ + if ((elm)->field.cqe_prev->field.cqe_next != (elm)) \ + panic("CIRCLEQ elm prev %p %s:%d", (elm), \ + __FILE__, __LINE__); \ + } +#define QUEUEDEBUG_CIRCLEQ_POSTREMOVE(elm, field) \ + (elm)->field.cqe_next = (void *)1L; \ + (elm)->field.cqe_prev = (void *)1L; +#else +#define QUEUEDEBUG_CIRCLEQ_HEAD(head, field) +#define QUEUEDEBUG_CIRCLEQ_ELM(head, elm, field) +#define QUEUEDEBUG_CIRCLEQ_POSTREMOVE(elm, field) +#endif + +#define CIRCLEQ_HEAD(name, type) \ +struct name { \ + struct type *cqh_first; /* first element */ \ + struct type *cqh_last; /* last element */ \ +} + +#define CIRCLEQ_HEAD_INITIALIZER(head) \ + { (void *)&head, (void *)&head } + +#define CIRCLEQ_ENTRY(type) \ +struct { \ + struct type *cqe_next; /* next element */ \ + struct type *cqe_prev; /* previous element */ \ +} + +/* + * Circular queue functions. + */ +#define CIRCLEQ_INIT(head) do { \ + (head)->cqh_first = (void *)(head); \ + (head)->cqh_last = (void *)(head); \ +} while (/* CONSTCOND */0) + +#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \ + QUEUEDEBUG_CIRCLEQ_ELM((head), (listelm), field) \ + (elm)->field.cqe_next = (listelm)->field.cqe_next; \ + (elm)->field.cqe_prev = (listelm); \ + if ((listelm)->field.cqe_next == (void *)(head)) \ + (head)->cqh_last = (elm); \ + else \ + (listelm)->field.cqe_next->field.cqe_prev = (elm); \ + (listelm)->field.cqe_next = (elm); \ +} while (/* CONSTCOND */0) + +#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ + QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \ + QUEUEDEBUG_CIRCLEQ_ELM((head), (listelm), field) \ + (elm)->field.cqe_next = (listelm); \ + (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ + if ((listelm)->field.cqe_prev == (void *)(head)) \ + (head)->cqh_first = (elm); \ + else \ + (listelm)->field.cqe_prev->field.cqe_next = (elm); \ + (listelm)->field.cqe_prev = (elm); \ +} while (/* CONSTCOND */0) + +#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ + QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \ + (elm)->field.cqe_next = (head)->cqh_first; \ + (elm)->field.cqe_prev = (void *)(head); \ + if ((head)->cqh_last == (void *)(head)) \ + (head)->cqh_last = (elm); \ + else \ + (head)->cqh_first->field.cqe_prev = (elm); \ + (head)->cqh_first = (elm); \ +} while (/* CONSTCOND */0) + +#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ + QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \ + (elm)->field.cqe_next = (void *)(head); \ + (elm)->field.cqe_prev = (head)->cqh_last; \ + if ((head)->cqh_first == (void *)(head)) \ + (head)->cqh_first = (elm); \ + else \ + (head)->cqh_last->field.cqe_next = (elm); \ + (head)->cqh_last = (elm); \ +} while (/* CONSTCOND */0) + +#define CIRCLEQ_REMOVE(head, elm, field) do { \ + QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \ + QUEUEDEBUG_CIRCLEQ_ELM((head), (elm), field) \ + if ((elm)->field.cqe_next == (void *)(head)) \ + (head)->cqh_last = (elm)->field.cqe_prev; \ + else \ + (elm)->field.cqe_next->field.cqe_prev = \ + (elm)->field.cqe_prev; \ + if ((elm)->field.cqe_prev == (void *)(head)) \ + (head)->cqh_first = (elm)->field.cqe_next; \ + else \ + (elm)->field.cqe_prev->field.cqe_next = \ + (elm)->field.cqe_next; \ + QUEUEDEBUG_CIRCLEQ_POSTREMOVE((elm), field) \ +} while (/* CONSTCOND */0) + +#define CIRCLEQ_FOREACH(var, head, field) \ + for ((var) = ((head)->cqh_first); \ + (var) != (const void *)(head); \ + (var) = ((var)->field.cqe_next)) + +#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ + for ((var) = ((head)->cqh_last); \ + (var) != (const void *)(head); \ + (var) = ((var)->field.cqe_prev)) + +/* + * Circular queue access methods. + */ +#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head)) +#define CIRCLEQ_FIRST(head) ((head)->cqh_first) +#define CIRCLEQ_LAST(head) ((head)->cqh_last) +#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) +#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) + +#define CIRCLEQ_LOOP_NEXT(head, elm, field) \ + (((elm)->field.cqe_next == (void *)(head)) \ + ? ((head)->cqh_first) \ + : (elm->field.cqe_next)) +#define CIRCLEQ_LOOP_PREV(head, elm, field) \ + (((elm)->field.cqe_prev == (void *)(head)) \ + ? ((head)->cqh_last) \ + : (elm->field.cqe_prev)) + +#endif /* !_SYS_QUEUE_H_ */ diff --git a/lib/libutils/isoc/include/sys/types.h b/lib/libutils/isoc/include/sys/types.h new file mode 100644 index 00000000000..b9c64fb614e --- /dev/null +++ b/lib/libutils/isoc/include/sys/types.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef SYS_TYPES_H +#define SYS_TYPES_H +#include +#include +#include +#include + +typedef uintptr_t vaddr_t; +typedef uintptr_t paddr_t; + +typedef intptr_t ssize_t; + +#endif /*SYS_TYPES_H*/ diff --git a/lib/libutils/isoc/include/time.h b/lib/libutils/isoc/include/time.h new file mode 100644 index 00000000000..584494808fd --- /dev/null +++ b/lib/libutils/isoc/include/time.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TIME_H +#define TIME_H + +#include + +#endif /*TIME_H*/ diff --git a/lib/libutils/isoc/include/unistd.h b/lib/libutils/isoc/include/unistd.h new file mode 100644 index 00000000000..1de78909d39 --- /dev/null +++ b/lib/libutils/isoc/include/unistd.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef UNISTD_H +#define UNISTD_H + +#include +#include + +#define __ssize_t_defined +typedef int32_t ssize_t; + +#endif diff --git a/lib/libutils/isoc/include/wchar.h b/lib/libutils/isoc/include/wchar.h new file mode 100644 index 00000000000..90932742ad3 --- /dev/null +++ b/lib/libutils/isoc/include/wchar.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef WCHAR_H +#define WCHAR_H + +#endif /*WCHAR_H*/ diff --git a/lib/libutils/isoc/malloc_wrapper.c b/lib/libutils/isoc/malloc_wrapper.c new file mode 100644 index 00000000000..9b7d6eeca3b --- /dev/null +++ b/lib/libutils/isoc/malloc_wrapper.c @@ -0,0 +1,497 @@ +/* + * Parts of this file are copied from + * http://www.fourmilab.ch/smartall/ and restructured to suit our needs. + * Smartall is released as: + * + * This software is in the public domain. Permission to use, copy, modify, + * and distribute this software and its documentation for any purpose and + * without fee is hereby granted, without any conditions or restrictions. + * This software is provided "as is" without express or implied warranty. + */ + +/* + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ST BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Following switch are for debug purpose: + * #define ENABLE_MDBG + * #define MDBG_REALLOC_ENABLED + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef TEE_USE_DLMALLOC +#include "dlmalloc.h" +#endif + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +/* mdbg routines only rely on malloc and free */ +#ifdef TEE_USE_DLMALLOC +#define EFFECTIVE_FREE dlfree +#define EFFECTIVE_MALLOC dlmalloc +#elif defined TEE_USE_BASIC_MALLOC +#define EFFECTIVE_FREE basic_free +#define EFFECTIVE_MALLOC basic_malloc +#endif + +#ifdef TEE_USE_BASIC_MALLOC +/* + * Very basic malloc pool from heap. Used for TZ bringup. + */ +#define HEAPSIZE (1024 * 1024) +char _heap_address[HEAPSIZE]; +uint32_t _heap_offset; + +static void *basic_malloc(size_t size) +{ + const int align = 8; + void *pt = _heap_address + _heap_offset; + _heap_offset += align * ((size + (align - 1)) / align); + if (_heap_offset > HEAPSIZE) + return 0; /* malloc error */ + return pt; +} + +static void basic_free(void *p) +{ + /* no effective free */ +} +#endif + +/* + * ENABLE_MDBG - redirects malloc familly calls to track requesters + * + * Handle malloc, free and realloc. + */ +#ifdef ENABLE_MDBG + +struct mdbg_elem { + TAILQ_ENTRY(mdbg_elem) link; + size_t len; + const char *fname; + uint16_t line; + bool ignore; + /* + uint8_t data[len - sizeof(struct mdbg_elem)]; + uint8_t magic; + */ +}; + +TAILQ_HEAD(mdbg_head, mdbg_elem) mdbg_head = TAILQ_HEAD_INITIALIZER(mdbg_head); + +static bool bufimode; /* Buffers not tracked when True - Initialized to False*/ + +/* Allocate buffer, enqueing on the orphaned buffer tracking list. */ +static void *mdbg_buf_alloc(const char *fname, int lineno, size_t nbytes) +{ + uint8_t *cp; + void *buf = NULL; + + /* + * Note: Unix MALLOC actually permits a zero length to be passed and + * allocates a valid block with zero user bytes. Such a block can later + * be expanded with realloc(). We disallow this based on the belief + * that it's better to make a special case and allocate one byte in the + * rare case this is desired than to miss all the erroneous occurrences + * where buffer length calculation code results in a zero. + */ + + assert(nbytes > 0); + + nbytes += sizeof(struct mdbg_elem) + 1; + cp = EFFECTIVE_MALLOC(nbytes); + if (cp != NULL) { + struct mdbg_elem *e = (struct mdbg_elem *)(void *)cp; + + /* Enqueue buffer on allocated list */ + TAILQ_INSERT_TAIL(&mdbg_head, e, link); + e->len = nbytes; + e->fname = fname; + e->line = (uint16_t) lineno; + e->ignore = bufimode; + /* Emplace end-clobber detector at end of buffer */ + cp[nbytes - 1] = (((uintptr_t) cp) & 0xFF) ^ 0xC5; + /* Increment to user data start */ + buf = cp + sizeof(struct mdbg_elem); + } + return buf; +} + +static bool mdbg_check_buf_end(struct mdbg_elem *e) +{ + uint8_t *cp = (uint8_t *)e; + + /* + * The following check detects storing off the end of the allocated + * space in the buffer by comparing the end of buffer checksum with the + * address of the buffer. + */ + if ((cp[e->len - 1] != ((((uintptr_t) cp) & 0xFF) ^ 0xC5))) + return false; + + return true; +} + +static bool mdbg_check_buf(struct mdbg_elem *ap) +{ + struct mdbg_elem *e; + + /* Validate queue links */ + if (ap == NULL) + return false; + + e = TAILQ_NEXT(ap, link); + if (e != NULL && TAILQ_PREV(e, mdbg_head, link) != ap) + return false; + + e = TAILQ_PREV(ap, mdbg_head, link); + if (e != NULL && TAILQ_NEXT(e, link) != ap) + return false; + + return mdbg_check_buf_end(ap); +} + +/* + * Update free pool availability. free is never called except through this + * interface. free(x) is defined to generate a call to this routine. + */ +void mdbg_free(void *fp) +{ + uint8_t *cp; + struct mdbg_elem *e; + + /* It is OK to free NULL */ + if (fp == NULL) + return; + + cp = (uint8_t *)fp - sizeof(struct mdbg_elem); + assert(((uintptr_t) cp & 0x3) == 0); + e = (struct mdbg_elem *)(void *)cp; + + assert(mdbg_check_buf(e)); + + TAILQ_REMOVE(&mdbg_head, e, link); + + /* + * Now we wipe the contents of the just-released buffer with "designer + * garbage" (Duff Kurland's phrase) of alternating bits. This is + * intended to ruin the day for any miscreant who attempts to access + * data through a pointer into storage that's been previously released. + */ + memset(cp, 0xAA, e->len); + + EFFECTIVE_FREE(cp); +} + +/* Allocate buffer. NULL is returned if no memory was available. */ +void *mdbg_malloc(const char *fname, int lineno, size_t nbytes) +{ + void *buf; + + buf = mdbg_buf_alloc(fname, lineno, nbytes); + if (buf != NULL) { + /* + * To catch sloppy code that assumes buffers obtained from + * malloc() are zeroed, we preset the buffer contents to + * "designer garbage" consisting of alternating bits. + */ + memset(buf, 0x55, nbytes); + } + return buf; +} + +#ifdef MDBG_REALLOC_ENABLED +/* + * Adjust the size of a previously allocated buffer. Because of the need to + * maintain our control storage, mdbg_realloc must always allocate a new + * block and copy the data in the old block. This may result in programs + * which make heavy use of realloc() running much slower than normally. + */ +void *mdbg_realloc(const char *fname, int lineno, void *ptr, size_t size) +{ + size_t osize; + void *buf; + struct mdbg_elem *e; + + assert(size > 0 && ((uintptr_t) ptr & 0x3) == 0); + + /* If the old block pointer is NULL, treat realloc() as a malloc(). */ + if (ptr == NULL) + return mdbg_malloc(fname, lineno, size); + + /* + * If the old and new sizes are the same, be a nice guy and just return + * the buffer passed in. + */ + e = (struct mdbg_elem *)(void *)((uint8_t *)ptr - + sizeof(struct mdbg_elem)); + osize = e->len - sizeof(struct mdbg_elem) - 1; + if (size == osize) + return ptr; + + /* + * Sizes differ. Allocate a new buffer of the requested size. If we + * can't obtain such a buffer, return NULL from realloc() and leave the + * buffer in ptr intact. + */ + buf = mdbg_malloc(fname, lineno, size); + if (buf != NULL) { + memcpy(buf, ptr, MIN(size, osize)); + + /* All done. Free and dechain the original buffer. */ + mdbg_free(ptr); + } + return buf; +} +#endif /* MDBG_REALLOC_ENABLED */ + +/* Allocate an array and clear it to zero. */ +void *mdbg_calloc(const char *fname, int lineno, size_t nelem, size_t elsize) +{ + void *buf; + + buf = mdbg_buf_alloc(fname, lineno, nelem * elsize); + if (buf != NULL) + memset(buf, 0, nelem * elsize); + return buf; +} + +static void mdbg_print_buf(int bufdump, const char *stat_str, + struct mdbg_elem *e) +{ + size_t memsize = e->len - (sizeof(struct mdbg_elem) + 1); + static const char unknown[] = "unknown"; + const char *fname = e->fname; + + if (fname == NULL) + fname = unknown; + + DMSG("%s buffer: %d bytes %s:%d", stat_str, memsize, fname, e->line); + + if (bufdump > 1) { + void *buf = ((uint8_t *)e) + sizeof(struct mdbg_elem); + + HEX_PRINT_BUF(buf, memsize); + } +} + +/* Print orphaned buffers (and dump them if bufdumP is true). */ +void mdbg_dump(int bufdump) +{ + struct mdbg_elem *e; + +#ifdef MDBG_PRINT_LEAKS + DMSG("Checking for %sbuffers", bufdump == 0 ? "Orphaned " : ""); +#endif + + TAILQ_FOREACH(e, &mdbg_head, link) { + if (!mdbg_check_buf(e)) { + mdbg_print_buf(bufdump, "Clobbered", e); + break; + } +#ifdef MDBG_PRINT_LEAKS + if (bufdump > 0 || !e->ignore) + mdbg_print_buf(bufdump, + e->ignore ? "Ignore" : "Orphaned", e); +#endif + } +} + +/* + * Orphaned buffer detection can be disabled (for such items as buffers + * allocated during initialisation) by calling mdbg_static(1). Normal + * orphaned buffer detection can be re-enabled with mdbg_static(0). Note + * that all the other safeguards still apply to buffers allocated when + * mdbg_static(1) mode is in effect. + */ +enum mdbg_mode mdbg_set_mode(enum mdbg_mode mode) +{ + enum mdbg_mode old_mode; + + if (bufimode) + old_mode = MDBG_MODE_STATIC; + else + old_mode = MDBG_MODE_DYNAMIC; + + if (mode == MDBG_MODE_STATIC) + bufimode = true; + else + bufimode = false; + + return old_mode; +} + +/* Trap PC with message if mdbg traces are corrupted */ +void mdbg_check(void) +{ + struct mdbg_elem *e; + + TAILQ_FOREACH(e, &mdbg_head, link) { + if (!mdbg_check_buf(e)) { + mdbg_print_buf(0, "Clobbered", e); + assert(0); + } + } +} + +#else /* ENABLE_MDBG */ + +/* + * case MDBG is not used: wrap each malloc service to the right handler. + */ +void free(void *ptr) +{ + EFFECTIVE_FREE(ptr); +} + +void *malloc(size_t size) +{ + return EFFECTIVE_MALLOC(size); +} + +void *calloc(size_t nmemb, size_t size) +{ +#ifdef TEE_USE_DLMALLOC + return dlcalloc(nmemb, size); +#else + size_t l = nmemb * size; + void *p = malloc(l); + + if (p != NULL) + memset(p, 0, l); + return p; +#endif +} + +void *realloc(void *ptr, size_t size) +{ +#ifdef TEE_USE_DLMALLOC + return dlrealloc(ptr, size); +#else + assert(0); + return NULL; +#endif +} + +/******************************************************************************/ + +/* + * Other standard mem alloc APIs, if supported! + */ +#ifdef TEE_USE_DLMALLOC /* these are only supported by dlmalloc */ +void *memalign(size_t a, size_t l) +{ + unsigned long i, j; + + /* check a is a power of 2 */ + for (i = 1, j = 0; i; i <<= 1) { + if (i & a) + j++; + } + if (j != 1) + return NULL; + + return dlmemalign(a, l); +} + +void *valloc(size_t l) +{ + if (l) { + EMSG("- assert: valloc from dlmalloc is not yet tested -"); + assert(0); + } + return dlvalloc(l); +} + +void *pvalloc(size_t l) +{ + if (l) { + EMSG("- assert: pvalloc from dlmalloc is not yet tested -"); + assert(0); + } + return dlpvalloc(l); +} +#endif /* TEE_USE_DLMALLOC */ + +#ifdef TEE_USE_DLMALLOC +/* + * brk for dlmalloc to get memory chunks. + */ +struct dlmalloc_area { + void *start; + void *end; + void *brk; +}; +static struct dlmalloc_area dla = { + .start = (void *)-1, +}; + +void *sbrk(ptrdiff_t size) +{ + void *cur; + + if ((dla.start == (void *)-1) || + ((unsigned long)dla.brk + size < (unsigned long)dla.start) || + ((unsigned long)dla.brk + size > (unsigned long)dla.end)) { + return (void *)-1; + } + + /* update brk for next request */ + cur = dla.brk; + dla.brk = (void *)((unsigned long)dla.brk + size); + + /* if releasing memory, insure clear content for next time */ + if (size < 0) + memset(dla.brk, 0, -size); + + return cur; +} + +static void dlmalloc_init(void *start, size_t size); + +static void dlmalloc_init(void *start, size_t size) +{ + /* + * TODO: map the malloc pool + * Thi is not currently required as malloc pool is already mapped + * at boot time from core_mmu.c/core_init_mmu(). + * But sooner, we shall map it at run time. + */ + + memset(start, 0, size); + dla.brk = start; + dla.start = start; + dla.end = (void *)((unsigned long)start + size); +} +#endif /* TEE_USE_DLMALLOC */ + +/* + * Malloc support init routine + */ +void malloc_init(void *start, size_t size) +{ +#ifdef TEE_USE_DLMALLOC + dlmalloc_init(start, size); +#endif +} + +#endif /* !ENABLE_MDBG */ diff --git a/lib/libutils/isoc/newlib/_ansi.h b/lib/libutils/isoc/newlib/_ansi.h new file mode 100644 index 00000000000..8b5347e9b60 --- /dev/null +++ b/lib/libutils/isoc/newlib/_ansi.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 1994-2009 Red Hat, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Provide support for both ANSI and non-ANSI environments. */ + +/* Some ANSI environments are "broken" in the sense that __STDC__ cannot be + relied upon to have it's intended meaning. Therefore we must use our own + concoction: _HAVE_STDC. Always use _HAVE_STDC instead of __STDC__ in newlib + sources! + + To get a strict ANSI C environment, define macro __STRICT_ANSI__. This will + "comment out" the non-ANSI parts of the ANSI header files (non-ANSI header + files aren't affected). */ + +#ifndef _ANSIDECL_H_ +#define _ANSIDECL_H_ + +/*#include */ +/*#include */ + +/* + * First try to figure out whether we really are in an ANSI C environment. + * This probably needs some work. Perhaps sys/config.h can be + * prevailed upon to give us a clue. + */ + +#ifdef __STDC__ +#define _HAVE_STDC +#endif + +#ifdef _HAVE_STDC +#define _PTR void * +#define _AND , +#define _NOARGS void +#define _CONST const +#define _VOLATILE volatile +#define _SIGNED signed +#define _DOTS , ... +#define _VOID void +#ifdef __CYGWIN__ +#define _EXFUN(name, proto) __cdecl name proto +#define _EXPARM(name, proto) (* __cdecl name) proto +#else +#define _EXFUN(name, proto) name proto +#define _EXPARM(name, proto) (* name) proto +#endif +#define _DEFUN(name, arglist, args) name(args) +#define _DEFUN_VOID(name) name(_NOARGS) +#define _CAST_VOID (void) +#ifndef _LONG_DOUBLE +#define _LONG_DOUBLE long double +#endif +#ifndef _PARAMS +#define _PARAMS(paramlist) paramlist +#endif +#else +#define _PTR char * +#define _AND ; +#define _NOARGS +#define _CONST +#define _VOLATILE +#define _SIGNED +#define _DOTS +#define _VOID void +#define _EXFUN(name, proto) name() +#define _DEFUN(name, arglist, args) name arglist args; +#define _DEFUN_VOID(name) name() +#define _CAST_VOID +#define _LONG_DOUBLE double +#ifndef _PARAMS +#define _PARAMS(paramlist) () +#endif +#endif + +/* Support gcc's __attribute__ facility. */ + +#ifdef __GNUC__ +#define _ATTRIBUTE(attrs) __attribute__ (attrs) +#else +#define _ATTRIBUTE(attrs) +#endif + +/* ISO C++. */ + +#ifdef __cplusplus +#if !(defined(_BEGIN_STD_C) && defined(_END_STD_C)) +#ifdef _HAVE_STD_CXX +#define _BEGIN_STD_C namespace std { extern "C" { +#define _END_STD_C } } +#else +#define _BEGIN_STD_C extern "C" { +#define _END_STD_C } +#endif +#endif +#else +#define _BEGIN_STD_C +#define _END_STD_C +#endif + +#endif /* _ANSIDECL_H_ */ diff --git a/lib/libutils/isoc/newlib/memchr.c b/lib/libutils/isoc/newlib/memchr.c new file mode 100644 index 00000000000..91f00acefd0 --- /dev/null +++ b/lib/libutils/isoc/newlib/memchr.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 1994-2009 Red Hat, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* +FUNCTION + <>---find character in memory + +INDEX + memchr + +ANSI_SYNOPSIS + #include + void *memchr(const void *<[src]>, int <[c]>, size_t <[length]>); + +TRAD_SYNOPSIS + #include + void *memchr(<[src]>, <[c]>, <[length]>) + void *<[src]>; + void *<[c]>; + size_t <[length]>; + +DESCRIPTION + This function searches memory starting at <<*<[src]>>> for the + character <[c]>. The search only ends with the first + occurrence of <[c]>, or after <[length]> characters; in + particular, <> does not terminate the search. + +RETURNS + If the character <[c]> is found within <[length]> characters + of <<*<[src]>>>, a pointer to the character is returned. If + <[c]> is not found, then <> is returned. + +PORTABILITY +<> is ANSI C. + +<> requires no supporting OS subroutines. + +QUICKREF + memchr ansi pure +*/ + +#include "_ansi.h" +#include +#include + +/* Nonzero if either X or Y is not aligned on a "long" boundary. */ +#define UNALIGNED(X) ((long)X & (sizeof(long) - 1)) + +/* How many bytes are loaded each iteration of the word copy loop. */ +#define LBLOCKSIZE (sizeof(long)) + +/* Threshhold for punting to the bytewise iterator. */ +#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) + +#if LONG_MAX == 2147483647L +#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) +#else +#if LONG_MAX == 9223372036854775807L +/* Nonzero if X (a long int) contains a NULL byte. */ +#define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) +#else +#error long int is not a 32bit or 64bit type. +#endif +#endif + +#ifndef DETECTNULL +#error long int is not a 32bit or 64bit byte +#endif + +/* DETECTCHAR returns nonzero if (long)X contains the byte used + to fill (long)MASK. */ +#define DETECTCHAR(X, MASK) (DETECTNULL(X ^ MASK)) + +_PTR +_DEFUN(memchr, (src_void, c, length), _CONST _PTR src_void _AND int c + _AND size_t length) +{ + _CONST unsigned char *src = (_CONST unsigned char *)src_void; + unsigned char d = c; + +#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) + unsigned long *asrc; + unsigned long mask; + int i; + + while (UNALIGNED(src)) { + if (!length--) + return NULL; + if (*src == d) + return (void *)src; + src++; + } + + if (!TOO_SMALL(length)) { + /* If we get this far, we know that length is large and src is + word-aligned. */ + /* The fast code reads the source one word at a time and only + performs the bytewise search on word-sized segments if they + contain the search character, which is detected by XORing + the word-sized segment with a word-sized block of the search + character and then detecting for the presence of NUL in the + result. */ + asrc = (unsigned long *)src; + mask = d << 8 | d; + mask = mask << 16 | mask; + for (i = 32; i < LBLOCKSIZE * 8; i <<= 1) + mask = (mask << i) | mask; + + while (length >= LBLOCKSIZE) { + if (DETECTCHAR(*asrc, mask)) + break; + length -= LBLOCKSIZE; + asrc++; + } + + /* If there are fewer than LBLOCKSIZE characters left, + then we resort to the bytewise loop. */ + + src = (unsigned char *)asrc; + } +#endif /* not PREFER_SIZE_OVER_SPEED */ + + while (length--) { + if (*src == d) + return (void *)src; + src++; + } + + return NULL; +} diff --git a/lib/libutils/isoc/newlib/memcmp.c b/lib/libutils/isoc/newlib/memcmp.c new file mode 100644 index 00000000000..eb29c54ec47 --- /dev/null +++ b/lib/libutils/isoc/newlib/memcmp.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 1994-2009 Red Hat, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* +FUNCTION + <>---compare two memory areas + +INDEX + memcmp + +ANSI_SYNOPSIS + #include + int memcmp(const void *<[s1]>, const void *<[s2]>, size_t <[n]>); + +TRAD_SYNOPSIS + #include + int memcmp(<[s1]>, <[s2]>, <[n]>) + void *<[s1]>; + void *<[s2]>; + size_t <[n]>; + +DESCRIPTION + This function compares not more than <[n]> characters of the + object pointed to by <[s1]> with the object pointed to by <[s2]>. + +RETURNS + The function returns an integer greater than, equal to or + less than zero according to whether the object pointed to by + <[s1]> is greater than, equal to or less than the object + pointed to by <[s2]>. + +PORTABILITY +<> is ANSI C. + +<> requires no supporting OS subroutines. + +QUICKREF + memcmp ansi pure +*/ + +#include "_ansi.h" +#include + +/* Nonzero if either X or Y is not aligned on a "long" boundary. */ +#define UNALIGNED(X, Y) \ + (((long)X & (sizeof(long) - 1)) | ((long)Y & (sizeof(long) - 1))) + +/* How many bytes are copied each iteration of the word copy loop. */ +#define LBLOCKSIZE (sizeof(long)) + +/* Threshhold for punting to the byte copier. */ +#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) + +int +_DEFUN(memcmp, (m1, m2, n), _CONST _PTR m1 _AND _CONST _PTR m2 _AND size_t n) +{ +#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) + unsigned char *s1 = (unsigned char *)m1; + unsigned char *s2 = (unsigned char *)m2; + + while (n--) { + if (*s1 != *s2) + return *s1 - *s2; + s1++; + s2++; + } + return 0; +#else + unsigned char *s1 = (unsigned char *)m1; + unsigned char *s2 = (unsigned char *)m2; + unsigned long *a1; + unsigned long *a2; + + /* If the size is too small, or either pointer is unaligned, + then we punt to the byte compare loop. Hopefully this will + not turn up in inner loops. */ + if (!TOO_SMALL(n) && !UNALIGNED(s1, s2)) { + /* + * Otherwise, load and compare the blocks of memory one word at + * a time. + */ + a1 = (unsigned long *)s1; + a2 = (unsigned long *)s2; + while (n >= LBLOCKSIZE) { + if (*a1 != *a2) + break; + a1++; + a2++; + n -= LBLOCKSIZE; + } + + /* check m mod LBLOCKSIZE remaining characters */ + + s1 = (unsigned char *)a1; + s2 = (unsigned char *)a2; + } + + while (n--) { + if (*s1 != *s2) + return *s1 - *s2; + s1++; + s2++; + } + + return 0; +#endif /* not PREFER_SIZE_OVER_SPEED */ +} diff --git a/lib/libutils/isoc/newlib/memcpy.c b/lib/libutils/isoc/newlib/memcpy.c new file mode 100644 index 00000000000..8cd8d7c75b9 --- /dev/null +++ b/lib/libutils/isoc/newlib/memcpy.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 1994-2009 Red Hat, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* +FUNCTION + <>---copy memory regions + +ANSI_SYNOPSIS + #include + void* memcpy(void *<[out]>, const void *<[in]>, size_t <[n]>); + +TRAD_SYNOPSIS + #include + void *memcpy(<[out]>, <[in]>, <[n]> + void *<[out]>; + void *<[in]>; + size_t <[n]>; + +DESCRIPTION + This function copies <[n]> bytes from the memory region + pointed to by <[in]> to the memory region pointed to by + <[out]>. + + If the regions overlap, the behavior is undefined. + +RETURNS + <> returns a pointer to the first byte of the <[out]> + region. + +PORTABILITY +<> is ANSI C. + +<> requires no supporting OS subroutines. + +QUICKREF + memcpy ansi pure +*/ + +#include "_ansi.h" +#include + +/* Nonzero if either X or Y is not aligned on a "long" boundary. */ +#define UNALIGNED(X, Y) \ + (((long)X & (sizeof(long) - 1)) | ((long)Y & (sizeof(long) - 1))) + +/* How many bytes are copied each iteration of the 4X unrolled loop. */ +#define BIGBLOCKSIZE (sizeof(long) << 2) + +/* How many bytes are copied each iteration of the word copy loop. */ +#define LITTLEBLOCKSIZE (sizeof(long)) + +/* Threshhold for punting to the byte copier. */ +#define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE) + +_PTR +_DEFUN(memcpy, (dst0, src0, len0), _PTR dst0 _AND _CONST _PTR src0 _AND + size_t len0) +{ +#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) + char *dst = (char *)dst0; + char *src = (char *)src0; + + _PTR save = dst0; + + while (len0--) + *dst++ = *src++; + + return save; +#else + char *dst = dst0; + _CONST char *src = src0; + long *aligned_dst; + _CONST long *aligned_src; + + /* If the size is small, or either SRC or DST is unaligned, + then punt into the byte copy loop. This should be rare. */ + if (!TOO_SMALL(len0) && !UNALIGNED(src, dst)) { + aligned_dst = (long *)dst; + aligned_src = (long *)src; + + /* Copy 4X long words at a time if possible. */ + while (len0 >= BIGBLOCKSIZE) { + *aligned_dst++ = *aligned_src++; + *aligned_dst++ = *aligned_src++; + *aligned_dst++ = *aligned_src++; + *aligned_dst++ = *aligned_src++; + len0 -= BIGBLOCKSIZE; + } + + /* Copy one long word at a time if possible. */ + while (len0 >= LITTLEBLOCKSIZE) { + *aligned_dst++ = *aligned_src++; + len0 -= LITTLEBLOCKSIZE; + } + + /* Pick up any residual with a byte copier. */ + dst = (char *)aligned_dst; + src = (char *)aligned_src; + } + + while (len0--) + *dst++ = *src++; + + return dst0; +#endif /* not PREFER_SIZE_OVER_SPEED */ +} diff --git a/lib/libutils/isoc/newlib/memmove.c b/lib/libutils/isoc/newlib/memmove.c new file mode 100644 index 00000000000..a4f0e3adef0 --- /dev/null +++ b/lib/libutils/isoc/newlib/memmove.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 1994-2009 Red Hat, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* +FUNCTION + <>---move possibly overlapping memory + +INDEX + memmove + +ANSI_SYNOPSIS + #include + void *memmove(void *<[dst]>, const void *<[src]>, size_t <[length]>); + +TRAD_SYNOPSIS + #include + void *memmove(<[dst]>, <[src]>, <[length]>) + void *<[dst]>; + void *<[src]>; + size_t <[length]>; + +DESCRIPTION + This function moves <[length]> characters from the block of + memory starting at <<*<[src]>>> to the memory starting at + <<*<[dst]>>>. <> reproduces the characters correctly + at <<*<[dst]>>> even if the two areas overlap. + +RETURNS + The function returns <[dst]> as passed. + +PORTABILITY +<> is ANSI C. + +<> requires no supporting OS subroutines. + +QUICKREF + memmove ansi pure +*/ + +#include +#include "_ansi.h" +#include +#include + +/* Nonzero if either X or Y is not aligned on a "long" boundary. */ +#define UNALIGNED(X, Y) \ + (((long)X & (sizeof(long) - 1)) | ((long)Y & (sizeof(long) - 1))) + +/* How many bytes are copied each iteration of the 4X unrolled loop. */ +#define BIGBLOCKSIZE (sizeof(long) << 2) + +/* How many bytes are copied each iteration of the word copy loop. */ +#define LITTLEBLOCKSIZE (sizeof(long)) + +/* Threshhold for punting to the byte copier. */ +#define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE) + +/* SUPPRESS 20 */ +_PTR +_DEFUN(memmove, (dst_void, src_void, length), _PTR dst_void _AND _CONST _PTR + src_void _AND size_t length) +{ +#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) + char *dst = dst_void; + _CONST char *src = src_void; + + if (src < dst && dst < src + length) { + /* Have to copy backwards */ + src += length; + dst += length; + while (length--) + *--dst = *--src; + } else { + while (length--) + *dst++ = *src++; + } + + return dst_void; +#else + char *dst = dst_void; + _CONST char *src = src_void; + long *aligned_dst; + _CONST long *aligned_src; + + if (src < dst && dst < src + length) { + /* Destructive overlap...have to copy backwards */ + src += length; + dst += length; + while (length--) + *--dst = *--src; + } else { + /* + * Use optimizing algorithm for a non-destructive copy to + * closely match memcpy. If the size is small or either SRC or + * DST is unaligned, then punt into the byte copy loop. This + * should be rare. + */ + if (!TOO_SMALL(length) && !UNALIGNED(src, dst)) { + aligned_dst = (long *)dst; + aligned_src = (long *)src; + + /* Copy 4X long words at a time if possible. */ + while (length >= BIGBLOCKSIZE) { + *aligned_dst++ = *aligned_src++; + *aligned_dst++ = *aligned_src++; + *aligned_dst++ = *aligned_src++; + *aligned_dst++ = *aligned_src++; + length -= BIGBLOCKSIZE; + } + + /* Copy one long word at a time if possible. */ + while (length >= LITTLEBLOCKSIZE) { + *aligned_dst++ = *aligned_src++; + length -= LITTLEBLOCKSIZE; + } + + /* Pick up any residual with a byte copier. */ + dst = (char *)aligned_dst; + src = (char *)aligned_src; + } + + while (length--) + *dst++ = *src++; + } + + return dst_void; +#endif /* not PREFER_SIZE_OVER_SPEED */ +} diff --git a/lib/libutils/isoc/newlib/memset.c b/lib/libutils/isoc/newlib/memset.c new file mode 100644 index 00000000000..09eca316f5c --- /dev/null +++ b/lib/libutils/isoc/newlib/memset.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 1994-2009 Red Hat, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* +FUNCTION + <>---set an area of memory + +INDEX + memset + +ANSI_SYNOPSIS + #include + void *memset(void *<[dst]>, int <[c]>, size_t <[length]>); + +TRAD_SYNOPSIS + #include + void *memset(<[dst]>, <[c]>, <[length]>) + void *<[dst]>; + int <[c]>; + size_t <[length]>; + +DESCRIPTION + This function converts the argument <[c]> into an unsigned + char and fills the first <[length]> characters of the array + pointed to by <[dst]> to the value. + +RETURNS + <> returns the value of <[dst]>. + +PORTABILITY +<> is ANSI C. + + <> requires no supporting OS subroutines. + +QUICKREF + memset ansi pure +*/ + +#include "_ansi.h" +#include + +#define LBLOCKSIZE (sizeof(long)) +#define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1)) +#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) + +_PTR _DEFUN(memset, (m, c, n), _PTR m _AND int c _AND size_t n) +{ + char *s = (char *)m; + +#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) + int i; + unsigned long buffer; + unsigned long *aligned_addr; + unsigned int d = c & 0xff; /* To avoid sign extension, copy C to an + unsigned variable. */ + + while (UNALIGNED(s)) { + if (n--) + *s++ = (char)c; + else + return m; + } + + if (!TOO_SMALL(n)) { + /* + * If we get this far, we know that n is large and s is + * word-aligned. + */ + aligned_addr = (unsigned long *)s; + + /* Store D into each char sized location in BUFFER so that + we can set large blocks quickly. */ + buffer = (d << 8) | d; + buffer |= (buffer << 16); + for (i = 32; i < LBLOCKSIZE * 8; i <<= 1) + buffer = (buffer << i) | buffer; + + /* Unroll the loop. */ + while (n >= LBLOCKSIZE * 4) { + *aligned_addr++ = buffer; + *aligned_addr++ = buffer; + *aligned_addr++ = buffer; + *aligned_addr++ = buffer; + n -= 4 * LBLOCKSIZE; + } + + while (n >= LBLOCKSIZE) { + *aligned_addr++ = buffer; + n -= LBLOCKSIZE; + } + /* Pick up the remainder with a bytewise loop. */ + s = (char *)aligned_addr; + } +#endif /* not PREFER_SIZE_OVER_SPEED */ + + while (n--) + *s++ = (char)c; + + return m; +} diff --git a/lib/libutils/isoc/newlib/strcmp.c b/lib/libutils/isoc/newlib/strcmp.c new file mode 100644 index 00000000000..0867f54c10e --- /dev/null +++ b/lib/libutils/isoc/newlib/strcmp.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 1994-2009 Red Hat, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* This file is copied from newlib-1.19 */ + +/* +FUNCTION + <>---character string compare + +INDEX + strcmp + +ANSI_SYNOPSIS + #include + int strcmp(const char *<[a]>, const char *<[b]>); + +TRAD_SYNOPSIS + #include + int strcmp(<[a]>, <[b]>) + char *<[a]>; + char *<[b]>; + +DESCRIPTION + <> compares the string at <[a]> to + the string at <[b]>. + +RETURNS + If <<*<[a]>>> sorts lexicographically after <<*<[b]>>>, + <> returns a number greater than zero. If the two + strings match, <> returns zero. If <<*<[a]>>> + sorts lexicographically before <<*<[b]>>>, <> returns a + number less than zero. + +PORTABILITY +<> is ANSI C. + +<> requires no supporting OS subroutines. + +QUICKREF + strcmp ansi pure +*/ + +#include "_ansi.h" +#include +#include + +/* Nonzero if either X or Y is not aligned on a "long" boundary. */ +#define UNALIGNED(X, Y) \ + (((long)X & (sizeof(long) - 1)) | ((long)Y & (sizeof(long) - 1))) + +/* DETECTNULL returns nonzero if (long)X contains a NULL byte. */ +#if LONG_MAX == 2147483647L +#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) +#else +#if LONG_MAX == 9223372036854775807L +#define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) +#else +#error long int is not a 32bit or 64bit type. +#endif +#endif + +#ifndef DETECTNULL +#error long int is not a 32bit or 64bit byte +#endif + +int _DEFUN(strcmp, (s1, s2), _CONST char *s1 _AND _CONST char *s2) +{ +#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) + while (*s1 != '\0' && *s1 == *s2) { + s1++; + s2++; + } + + return (*(unsigned char *)s1) - (*(unsigned char *)s2); +#else + unsigned long *a1; + unsigned long *a2; + + /* If s1 or s2 are unaligned, then compare bytes. */ + if (!UNALIGNED(s1, s2)) { + /* + * If s1 and s2 are word-aligned, compare them a word at a time. + */ + a1 = (unsigned long *)s1; + a2 = (unsigned long *)s2; + while (*a1 == *a2) { + /* + * To get here, *a1 == *a2, thus if we find a null in + * *a1, then the strings must be equal, so return zero. + */ + if (DETECTNULL(*a1)) + return 0; + + a1++; + a2++; + } + + /* + * A difference was detected in last few bytes of s1, so search + * bytewise. + */ + s1 = (char *)a1; + s2 = (char *)a2; + } + + while (*s1 != '\0' && *s1 == *s2) { + s1++; + s2++; + } + return (*(unsigned char *)s1) - (*(unsigned char *)s2); +#endif /* not PREFER_SIZE_OVER_SPEED */ +} diff --git a/lib/libutils/isoc/newlib/strlen.c b/lib/libutils/isoc/newlib/strlen.c new file mode 100644 index 00000000000..ca823b778c0 --- /dev/null +++ b/lib/libutils/isoc/newlib/strlen.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 1994-2009 Red Hat, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* This file is copied from newlib-1.19 */ + +/* +FUNCTION + <>---character string length + +INDEX + strlen + +ANSI_SYNOPSIS + #include + size_t strlen(const char *<[str]>); + +TRAD_SYNOPSIS + #include + size_t strlen(<[str]>) + char *<[src]>; + +DESCRIPTION + The <> function works out the length of the string + starting at <<*<[str]>>> by counting chararacters until it + reaches a <> character. + +RETURNS + <> returns the character count. + +PORTABILITY +<> is ANSI C. + +<> requires no supporting OS subroutines. + +QUICKREF + strlen ansi pure +*/ + +#include "_ansi.h" +#include +#include + +#define LBLOCKSIZE (sizeof(long)) +#define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1)) + +#if LONG_MAX == 2147483647L +#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) +#else +#if LONG_MAX == 9223372036854775807L +/* Nonzero if X (a long int) contains a NULL byte. */ +#define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) +#else +#error long int is not a 32bit or 64bit type. +#endif +#endif + +#ifndef DETECTNULL +#error long int is not a 32bit or 64bit byte +#endif + +size_t _DEFUN(strlen, (str), _CONST char *str) +{ + _CONST char *start = str; + +#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) + unsigned long *aligned_addr; + + /* Align the pointer, so we can search a word at a time. */ + while (UNALIGNED(str)) { + if (!*str) + return str - start; + str++; + } + + /* If the string is word-aligned, we can check for the presence of + a null in each word-sized block. */ + aligned_addr = (unsigned long *)str; + while (!DETECTNULL(*aligned_addr)) + aligned_addr++; + + /* Once a null is detected, we check each byte in that block for a + precise position of the null. */ + str = (char *)aligned_addr; + +#endif /* not PREFER_SIZE_OVER_SPEED */ + + while (*str) + str++; + return str - start; +} diff --git a/lib/libutils/isoc/newlib/strnlen.c b/lib/libutils/isoc/newlib/strnlen.c new file mode 100644 index 00000000000..4793b14873d --- /dev/null +++ b/lib/libutils/isoc/newlib/strnlen.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1994-2009 Red Hat, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* +FUNCTION + <>---character string length + +INDEX + strnlen + +ANSI_SYNOPSIS + #include + size_t strnlen(const char *<[str]>, size_t <[n]>); + +TRAD_SYNOPSIS + #include + size_t strnlen(<[str]>, <[n]>) + char *<[src]>; + size_t <[n]>; + +DESCRIPTION + The <> function works out the length of the string + starting at <<*<[str]>>> by counting chararacters until it + reaches a NUL character or the maximum: <[n]> number of + characters have been inspected. + +RETURNS + <> returns the character count or <[n]>. + +PORTABILITY +<> is a GNU extension. + +<> requires no supporting OS subroutines. + +*/ + +#undef __STRICT_ANSI__ +#include "_ansi.h" +#include + +size_t +_DEFUN (strnlen, (str, n), + _CONST char *str _AND + size_t n) +{ + _CONST char *start = str; + + while (n-- > 0 && *str) + str++; + + return str - start; +} diff --git a/lib/libutils/isoc/newlib/sub.mk b/lib/libutils/isoc/newlib/sub.mk new file mode 100644 index 00000000000..29a6660d21d --- /dev/null +++ b/lib/libutils/isoc/newlib/sub.mk @@ -0,0 +1,26 @@ +srcs-y += memchr.c +cflags-remove-memchr.c-y += -Wcast-align +cflags-memchr.c-y += -Wno-sign-compare + +srcs-y += memcmp.c +cflags-remove-memcmp.c-y += -Wcast-align + +srcs-y += memcpy.c +cflags-remove-memcpy.c-y += -Wcast-align + +srcs-y += memmove.c +cflags-remove-memmove.c-y += -Wcast-align + +srcs-y += memset.c +cflags-remove-memset.c-y += -Wcast-align +cflags-memset.c-y += -Wno-sign-compare + + +srcs-y += strcmp.c +cflags-remove-strcmp.c-y += -Wcast-align + +srcs-y += strlen.c +cflags-remove-strlen.c-y += -Wcast-align + +srcs-y += strnlen.c + diff --git a/lib/libutils/isoc/qsort.c b/lib/libutils/isoc/qsort.c new file mode 100644 index 00000000000..70a848e7146 --- /dev/null +++ b/lib/libutils/isoc/qsort.c @@ -0,0 +1,150 @@ +/* $OpenBSD: qsort.c,v 1.10 2005/08/08 08:05:37 espie Exp $ */ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include +#include +static __inline char + *med3(char *, char *, char *, int (*)(const void *, const void *)); +static __inline void swapfunc(char *, char *, int, int); +#define min(a, b) (a) < (b) ? a : b +/* + * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". + */ +#define swapcode(TYPE, parmi, parmj, n) { \ + long i = (n) / sizeof (TYPE); \ + TYPE *pi = (TYPE *) (parmi); \ + TYPE *pj = (TYPE *) (parmj); \ + do { \ + TYPE t = *pi; \ + *pi++ = *pj; \ + *pj++ = t; \ + } while (--i > 0); \ +} +#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ + es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; +static __inline void +swapfunc(char *a, char *b, int n, int swaptype) +{ + if (swaptype <= 1) + swapcode(long, a, b, n) + else + swapcode(char, a, b, n) +} +#define swap(a, b) \ + if (swaptype == 0) { \ + long t = *(long *)(a); \ + *(long *)(a) = *(long *)(b); \ + *(long *)(b) = t; \ + } else \ + swapfunc(a, b, es, swaptype) +#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) +static __inline char * +med3(char *a, char *b, char *c, int (*cmp)(const void *, const void *)) +{ + return cmp(a, b) < 0 ? + (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a )) + :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c )); +} +void +qsort(void *aa, size_t n, size_t es, int (*cmp)(const void *, const void *)) +{ + char *pa, *pb, *pc, *pd, *pl, *pm, *pn; + int d, r, swaptype, swap_cnt; + char *a = aa; + loop: SWAPINIT(a, es); + swap_cnt = 0; + if (n < 7) { + for (pm = (char *)a + es; pm < (char *) a + n * es; pm += es) + for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; + pl -= es) + swap(pl, pl - es); + return; + } + pm = (char *)a + (n / 2) * es; + if (n > 7) { + pl = (char *)a; + pn = (char *)a + (n - 1) * es; + if (n > 40) { + d = (n / 8) * es; + pl = med3(pl, pl + d, pl + 2 * d, cmp); + pm = med3(pm - d, pm, pm + d, cmp); + pn = med3(pn - 2 * d, pn - d, pn, cmp); + } + pm = med3(pl, pm, pn, cmp); + } + swap(a, pm); + pa = pb = (char *)a + es; + + pc = pd = (char *)a + (n - 1) * es; + for (;;) { + while (pb <= pc && (r = cmp(pb, a)) <= 0) { + if (r == 0) { + swap_cnt = 1; + swap(pa, pb); + pa += es; + } + pb += es; + } + while (pb <= pc && (r = cmp(pc, a)) >= 0) { + if (r == 0) { + swap_cnt = 1; + swap(pc, pd); + pd -= es; + } + pc -= es; + } + if (pb > pc) + break; + swap(pb, pc); + swap_cnt = 1; + pb += es; + pc -= es; + } + if (swap_cnt == 0) { /* Switch to insertion sort */ + for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es) + for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; + pl -= es) + swap(pl, pl - es); + return; + } + pn = (char *)a + n * es; + r = min(pa - (char *)a, pb - pa); + vecswap(a, pb - r, r); + r = min(pd - pc, pn - pd - (int)es); + vecswap(pb, pn - r, r); + if ((r = pb - pa) > (int)es) + qsort(a, r / es, es, cmp); + if ((r = pd - pc) > (int)es) { + /* Iterate rather than recurse to save stack space */ + a = pn - r; + n = r / es; + goto loop; + } + /* qsort(pn - r, r / es, es, cmp);*/ +} diff --git a/lib/libutils/isoc/snprintf.c b/lib/libutils/isoc/snprintf.c new file mode 100644 index 00000000000..0adbbaee403 --- /dev/null +++ b/lib/libutils/isoc/snprintf.c @@ -0,0 +1,545 @@ +/* + * Imported from NetBSD 5.1 with modifications to make it a vsnprintf(3) + * function + */ + +/* $NetBSD: subr_prf.c,v 1.124.4.1 2009/02/02 19:47:47 snj Exp $ */ + +/*- + * Copyright (c) 1986, 1988, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)subr_prf.c 8.4 (Berkeley) 5/4/95 + */ + +#include +#include +#include +#include +#include + +/* flags for kprintf */ +#define TOCONS 0x0001 /* to the console */ +#define TOTTY 0x0002 /* to the process' tty */ +#define TOLOG 0x0004 /* to the kernel message buffer */ +#define TOBUFONLY 0x0008 /* to the buffer (only) [for snprintf] */ +#define TODDB 0x0010 /* to ddb console */ +#define NOLOCK 0x1000 /* don't acquire a tty lock */ + +/* max size buffer kprintf needs to print quad_t [size in base 8 + \0] */ +#define KPRINTF_BUFSIZE 23 /*(8 * 8 / 3 + 2) */ + +/* + * The following macro is used to remove const cast-away warnings + * from gcc -Wcast-qual; it should be used with caution because it + * can hide valid errors; in particular most valid uses are in + * situations where the API requires it, not to cast away string + * constants. We don't use *intptr_t on purpose here and we are + * explicit about unsigned long so that we don't have additional + * dependencies. + */ +#define __UNCONST(a) ((void *)(unsigned long)(const void *)(a)) + +#define putchar(c, flags, tty) \ + do { (void)(c); (void)(flags); (void)(tty); } while(0) + +static int kprintf(const char *fmt0, int oflags, void *vp, char *sbuf, + va_list ap); + +static const char hexdigits[] = "0123456789abcdef"; +static const char HEXDIGITS[] = "0123456789ABCDEF"; + +/* + * snprintf: print a message to a buffer + */ +int snprintf(char *bf, size_t size, const char *fmt, ...) +{ + int retval; + va_list ap; + char *p; + + if (size < 1) + return -1; + p = bf + size - 1; + va_start(ap, fmt); + retval = kprintf(fmt, TOBUFONLY, &p, bf, ap); + va_end(ap); + *(p) = 0; /* null terminate */ + return retval; +} + +/* + * vsnprintf: print a message to a buffer [already have va_alist] + */ +int vsnprintf(char *bf, size_t size, const char *fmt, va_list ap) +{ + int retval; + char *p; + + if (size < 1) + return -1; + p = bf + size - 1; + retval = kprintf(fmt, TOBUFONLY, &p, bf, ap); + *(p) = 0; /* null terminate */ + return retval; +} + +/* + * kprintf: scaled down version of printf(3). + * + * this version based on vfprintf() from libc which was derived from + * software contributed to Berkeley by Chris Torek. + * + */ + +/* + * macros for converting digits to letters and vice versa + */ +#define to_digit(c) ((c) - '0') +#define is_digit(c) ((unsigned)to_digit(c) <= 9) +#define to_char(n) ((n) + '0') + +/* + * flags used during conversion. + */ +#define ALT 0x001 /* alternate form */ +#define HEXPREFIX 0x002 /* add 0x or 0X prefix */ +#define LADJUST 0x004 /* left adjustment */ +#define LONGDBL 0x008 /* long double; unimplemented */ +#define LONGINT 0x010 /* long integer */ +#define SHORTINT 0x040 /* short integer */ +#define MAXINT 0x080 /* intmax_t */ +#define PTRINT 0x100 /* intptr_t */ +#define SIZEINT 0x200 /* size_t */ +#define ZEROPAD 0x400 /* zero (as opposed to blank) pad */ +#define FPT 0x800 /* Floating point number */ + + /* + * To extend shorts properly, we need both signed and unsigned + * argument extraction methods. + */ +#define SARG() \ + (flags&MAXINT ? va_arg(ap, intmax_t) : \ + flags&PTRINT ? va_arg(ap, intptr_t) : \ + flags&SIZEINT ? va_arg(ap, ssize_t) : /* XXX */ \ + flags&LONGINT ? va_arg(ap, long) : \ + flags&SHORTINT ? (long)(short)va_arg(ap, int) : \ + (long)va_arg(ap, int)) +#define UARG() \ + (flags&MAXINT ? va_arg(ap, uintmax_t) : \ + flags&PTRINT ? va_arg(ap, uintptr_t) : \ + flags&SIZEINT ? va_arg(ap, size_t) : \ + flags&LONGINT ? va_arg(ap, unsigned long) : \ + flags&SHORTINT ? (unsigned long)(unsigned short)va_arg(ap, int) : \ + (unsigned long)va_arg(ap, unsigned)) + +#define KPRINTF_PUTCHAR(C) { \ + if (oflags == TOBUFONLY) { \ + if ((vp != NULL) && (sbuf == tailp)) { \ + ret += 1; /* indicate error */ \ + goto overflow; \ + } \ + *sbuf++ = (C); \ + } else { \ + putchar((C), oflags, (struct tty *)vp); \ + } \ + } + +/* + * Guts of kernel printf. Note, we already expect to be in a mutex! + */ +static int +kprintf(const char *fmt0, int oflags, void *vp, char *sbuf, va_list ap) +{ + const char *fmt; /* format string */ + int ch; /* character from fmt */ + int n; /* handy integer (short term usage) */ + char *cp; /* handy char pointer (short term usage) */ + int flags; /* flags as above */ + int ret; /* return value accumulator */ + int width; /* width from format (%8d), or 0 */ + int prec; /* precision from format (%.3d), or -1 */ + char sign; /* sign prefix (' ', '+', '-', or \0) */ + + uint32_t _uquad; /* integer arguments %[diouxX] */ + enum { OCT, DEC, HEX } base; /* base for [diouxX] conversion */ + int dprec; /* a copy of prec if [diouxX], 0 otherwise */ + int realsz; /* field size expanded by dprec */ + int size; /* size of converted field or string */ + const char *xdigs; /* digits for [xX] conversion */ + char bf[KPRINTF_BUFSIZE]; /* space for %c, %[diouxX] */ + char *tailp; /* tail pointer for snprintf */ + + tailp = NULL; /* XXX: shutup gcc */ + if (oflags == TOBUFONLY && (vp != NULL)) + tailp = *(char **)vp; + + cp = NULL; /* XXX: shutup gcc */ + size = 0; /* XXX: shutup gcc */ + + fmt = fmt0; + ret = 0; + + xdigs = NULL; /* XXX: shut up gcc warning */ + + /* + * Scan the format for conversions (`%' character). + */ + for (;;) { + while (*fmt != '%' && *fmt) { + ret++; + KPRINTF_PUTCHAR(*fmt++); + } + if (*fmt == 0) + goto done; + + fmt++; /* skip over '%' */ + + flags = 0; + dprec = 0; + width = 0; + prec = -1; + sign = '\0'; + +rflag: ch = *fmt++; +reswitch: switch (ch) { + case ' ': + /* + * ``If the space and + flags both appear, the space + * flag will be ignored.'' + * -- ANSI X3J11 + */ + if (!sign) + sign = ' '; + goto rflag; + case '#': + flags |= ALT; + goto rflag; + case '*': + /* + * ``A negative field width argument is taken as a + * - flag followed by a positive field width.'' + * -- ANSI X3J11 + * They don't exclude field widths read from args. + */ + if ((width = va_arg(ap, int)) >= 0) + goto rflag; + width = -width; + /* FALLTHROUGH */ + case '-': + flags |= LADJUST; + goto rflag; + case '+': + sign = '+'; + goto rflag; + case '.': + if ((ch = *fmt++) == '*') { + n = va_arg(ap, int); + prec = n < 0 ? -1 : n; + goto rflag; + } + n = 0; + while (is_digit(ch)) { + n = 10 * n + to_digit(ch); + ch = *fmt++; + } + prec = n < 0 ? -1 : n; + goto reswitch; + case '0': + /* + * ``Note that 0 is taken as a flag, not as the + * beginning of a field width.'' + * -- ANSI X3J11 + */ + flags |= ZEROPAD; + goto rflag; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + n = 0; + do { + n = 10 * n + to_digit(ch); + ch = *fmt++; + } while (is_digit(ch)); + width = n; + goto reswitch; + case 'h': + flags |= SHORTINT; + goto rflag; + case 'j': + flags |= MAXINT; + goto rflag; + case 'l': + flags |= LONGINT; + goto rflag; + case 't': + flags |= PTRINT; + goto rflag; + case 'z': + flags |= SIZEINT; + goto rflag; + case 'c': + *(cp = bf) = va_arg(ap, int); + size = 1; + sign = '\0'; + break; + case 'D': + flags |= LONGINT; + /* FALLTHROUGH */ case 'd': + case 'i': + _uquad = SARG(); + if ((int32_t) _uquad < 0) { + _uquad = -_uquad; + sign = '-'; + } + base = DEC; + goto number; + case 'n': + if (flags & MAXINT) + *va_arg(ap, intmax_t *) = ret; + else if (flags & PTRINT) + *va_arg(ap, intptr_t *) = ret; + else if (flags & SIZEINT) + *va_arg(ap, ssize_t *) = ret; + else if (flags & LONGINT) + *va_arg(ap, long *) = ret; + else if (flags & SHORTINT) + *va_arg(ap, short *) = ret; + else + *va_arg(ap, int *) = ret; + continue; /* no output */ + case 'O': + flags |= LONGINT; + /* FALLTHROUGH */ case 'o': + _uquad = UARG(); + base = OCT; + goto nosign; + case 'p': + /* + * ``The argument shall be a pointer to void. The + * value of the pointer is converted to a sequence + * of printable characters, in an implementation- + * defined manner.'' + * -- ANSI X3J11 + */ + /* NOSTRICT */ + _uquad = (unsigned long)va_arg(ap, void *); + base = HEX; + xdigs = hexdigits; + flags |= HEXPREFIX; + ch = 'x'; + goto nosign; + case 's': + if ((cp = va_arg(ap, char *)) == NULL) + /* XXXUNCONST */ cp = __UNCONST("(null)"); + if (prec >= 0) { + /* + * can't use strlen; can only look for the + * NUL in the first `prec' characters, and + * strlen() will go further. + */ + char *p = memchr(cp, 0, prec); + + if (p != NULL) { + size = p - cp; + if (size > prec) + size = prec; + } else { + size = prec; + } + } else { + size = strlen(cp); + } + sign = '\0'; + break; + case 'U': + flags |= LONGINT; + /* FALLTHROUGH */ case 'u': + _uquad = UARG(); + base = DEC; + goto nosign; + case 'X': + xdigs = HEXDIGITS; + goto hex; + case 'x': + xdigs = hexdigits; +hex: _uquad = UARG(); + base = HEX; + /* leading 0x/X only if non-zero */ + if (flags & ALT && _uquad != 0) + flags |= HEXPREFIX; + + /* unsigned conversions */ +nosign: sign = '\0'; + /* + * ``... diouXx conversions ... if a precision is + * specified, the 0 flag will be ignored.'' + * -- ANSI X3J11 + */ +number: if ((dprec = prec) >= 0) + flags &= ~ZEROPAD; + + /* + * ``The result of converting a zero value with an + * explicit precision of zero is no characters.'' + * -- ANSI X3J11 + */ + cp = bf + KPRINTF_BUFSIZE; + if (_uquad != 0 || prec != 0) { + /* + * Unsigned mod is hard, and unsigned mod + * by a constant is easier than that by + * a variable; hence this switch. + */ + switch (base) { + case OCT: + do { + *--cp = to_char(_uquad & 7); + _uquad >>= 3; + } while (_uquad); + /* handle octal leading 0 */ + if (flags & ALT && *cp != '0') + *--cp = '0'; + break; + + case DEC: + /* many numbers are 1 digit */ + while (_uquad >= 10) { + *--cp = to_char(_uquad % 10); + _uquad /= 10; + } + *--cp = to_char(_uquad); + break; + + case HEX: + do { + *--cp = xdigs[_uquad & 15]; + _uquad >>= 4; + } while (_uquad); + break; + + default: + /* XXXUNCONST */ + cp = + __UNCONST + ("bug in kprintf: bad base"); + size = strlen(cp); + goto skipsize; + } + } + size = bf + KPRINTF_BUFSIZE - cp; +skipsize: + break; + default: /* "%?" prints ?, unless ? is NUL */ + if (ch == '\0') + goto done; + /* pretend it was %c with argument ch */ + cp = bf; + *cp = ch; + size = 1; + sign = '\0'; + break; + } + + /* + * All reasonable formats wind up here. At this point, `cp' + * points to a string which (if not flags&LADJUST) should be + * padded out to `width' places. If flags&ZEROPAD, it should + * first be prefixed by any sign or other prefix; otherwise, + * it should be blank padded before the prefix is emitted. + * After any left-hand padding and prefixing, emit zeroes + * required by a decimal [diouxX] precision, then print the + * string proper, then emit zeroes required by any leftover + * floating precision; finally, if LADJUST, pad with blanks. + * + * Compute actual size, so we know how much to pad. + * size excludes decimal prec; realsz includes it. + */ + realsz = dprec > size ? dprec : size; + if (sign) + realsz++; + else if (flags & HEXPREFIX) + realsz += 2; + + /* adjust ret */ + ret += width > realsz ? width : realsz; + + /* right-adjusting blank padding */ + if ((flags & (LADJUST | ZEROPAD)) == 0) { + n = width - realsz; + while (n-- > 0) + KPRINTF_PUTCHAR(' '); + } + + /* prefix */ + if (sign) { + KPRINTF_PUTCHAR(sign); + } else if (flags & HEXPREFIX) { + KPRINTF_PUTCHAR('0'); + KPRINTF_PUTCHAR(ch); + } + + /* right-adjusting zero padding */ + if ((flags & (LADJUST | ZEROPAD)) == ZEROPAD) { + n = width - realsz; + while (n-- > 0) + KPRINTF_PUTCHAR('0'); + } + + /* leading zeroes from decimal precision */ + n = dprec - size; + while (n-- > 0) + KPRINTF_PUTCHAR('0'); + + /* the string or number proper */ + while (size--) + KPRINTF_PUTCHAR(*cp++); + /* left-adjusting padding (always blank) */ + if (flags & LADJUST) { + n = width - realsz; + while (n-- > 0) + KPRINTF_PUTCHAR(' '); + } + } + +done: + if ((oflags == TOBUFONLY) && (vp != NULL)) + *(char **)vp = sbuf; +overflow: + return ret; +} diff --git a/lib/libutils/isoc/stack_check.c b/lib/libutils/isoc/stack_check.c new file mode 100644 index 00000000000..5c11552ed17 --- /dev/null +++ b/lib/libutils/isoc/stack_check.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +void *__stack_chk_guard = (void *)0x00000aff; + +void __attribute__((noreturn)) __stack_chk_fail(void); + +void __stack_chk_fail(void) +{ + while (1) + ; +} + diff --git a/lib/libutils/isoc/strdup.c b/lib/libutils/isoc/strdup.c new file mode 100644 index 00000000000..59e7d1cb3dd --- /dev/null +++ b/lib/libutils/isoc/strdup.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include + +char *strdup(const char *s) +{ + size_t l = strlen(s) + 1; + char *p = malloc(l); + + if (p) + memcpy(p, s, l); + return p; +} diff --git a/lib/libutils/isoc/strndup.c b/lib/libutils/isoc/strndup.c new file mode 100644 index 00000000000..c6488d4d246 --- /dev/null +++ b/lib/libutils/isoc/strndup.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include + +char *strndup(const char *s, size_t n) +{ + size_t l = strnlen(s, n) + 1; + char *p = malloc(l); + + if (p) { + memcpy(p, s, l - 1); + p[l - 1] = '\0'; + } + return p; +} diff --git a/lib/libutils/isoc/sub.mk b/lib/libutils/isoc/sub.mk new file mode 100644 index 00000000000..cb2f034258d --- /dev/null +++ b/lib/libutils/isoc/sub.mk @@ -0,0 +1,20 @@ +global-incdirs-y += include + + +srcs-$(sm-core) += dlmalloc.c +cflags-remove-dlmalloc.c-y += -Wcast-align -Wstrict-aliasing=2 + +srcs-$(sm-core) += malloc_wrapper.c +cflags-malloc_wrapper.c-y += -Wno-redundant-decls + +srcs-y += snprintf.c + +srcs-y += stack_check.c +srcs-y += qsort.c +cflags-remove-qsort.c-y += -Wcast-align + +srcs-y += strdup.c +srcs-y += strndup.c + +subdirs-y += newlib +subdirs-$(arch_arm32) += arch/$(ARCH) diff --git a/lib/libutils/sub.mk b/lib/libutils/sub.mk new file mode 100644 index 00000000000..c9673f40071 --- /dev/null +++ b/lib/libutils/sub.mk @@ -0,0 +1,2 @@ +subdirs-$(libutil_with_isoc) += isoc +subdirs-y += ext diff --git a/mk/cleanvars.mk b/mk/cleanvars.mk new file mode 100644 index 00000000000..abbdfee9868 --- /dev/null +++ b/mk/cleanvars.mk @@ -0,0 +1,10 @@ +# Cleans all output variables from other make files to allow for a new start + +srcs := +objs := +libfiles := +libdirs := +libnames := +libdeps := +sm-$(sm) := +incdirs := diff --git a/mk/compile.mk b/mk/compile.mk new file mode 100644 index 00000000000..e18cd8c596b --- /dev/null +++ b/mk/compile.mk @@ -0,0 +1,114 @@ +# Input +# +# The output from mk/sub.mk +# base-prefix +# +# Output +# +# set objs +# update cleanfiles +# +# Generates explicit rules for all objs + +objs := + +# Disable all builtin rules +.SUFFIXES: + +comp-cflags$(sm) = -std=gnu99 +comp-aflags$(sm) = +comp-cppflags$(sm) = + +ifndef NOWERROR +comp-cflags$(sm) += -Werror +endif +comp-cflags$(sm) += -fdiagnostics-show-option + +comp-cflags-warns-high = \ + -Wall -Wcast-align \ + -Werror-implicit-function-declaration -Wextra -Wfloat-equal \ + -Wformat-nonliteral -Wformat-security -Wformat=2 -Winit-self \ + -Wmissing-declarations -Wmissing-format-attribute \ + -Wmissing-include-dirs -Wmissing-noreturn \ + -Wmissing-prototypes -Wnested-externs -Wpointer-arith \ + -Wshadow -Wstrict-prototypes -Wswitch-default \ + -Wwrite-strings \ + -Wno-missing-field-initializers -Wno-format-zero-length +comp-cflags-warns-medium = \ + -Waggregate-return -Wredundant-decls +comp-cflags-warns-low = \ + -Winline \ + -Wold-style-definition -Wstrict-aliasing=2 \ + -Wundef -pedantic \ + -Wdeclaration-after-statement + +comp-cflags-warns-1:= $(comp-cflags-warns-high) +comp-cflags-warns-2:= $(comp-cflags-warns-1) $(comp-cflags-warns-medium) +comp-cflags-warns-3:= $(comp-cflags-warns-2) $(comp-cflags-warns-low) + +WARNS ?= 3 + +comp-cflags$(sm) += $(comp-cflags-warns-$(WARNS)) + +.PHONY: FORCE +FORCE: + +define process_srcs +objs += $2 +comp-dep-$2 := $$(dir $2).$$(notdir $2).d +comp-temp-dep-$2:= $$(comp-dep-$2).tmp +comp-cmd-file-$2:= $$(dir $2).$$(notdir $2).cmd +comp-sm-$2 := $(sm) + +cleanfiles := $$(cleanfiles) $$(comp-dep-$2) $$(comp-cmd-file-$2) $2 + +ifeq ($$(filter %.c,$1),$1) +comp-flags-$2 = $$(filter-out $$(CFLAGS_REMOVE) $$(cflags-remove) \ + $$(cflags-remove-$2), \ + $$(CFLAGS) $$(CFLAGS_WARNS) \ + $$(comp-cflags$$(comp-sm-$2)) $$(cflags$$(comp-sm-$2)) \ + $$(cflags-$2)) +else ifeq ($$(filter %.S,$1),$1) +comp-flags-$2 = -DASM=1 $$(filter-out $$(AFLAGS_REMOVE) $$(aflags-remove) \ + $$(aflags-remove-$2), \ + $$(AFLAGS) $$(comp-aflags$$(comp-sm-$2)) \ + $$(aflags$$(comp-sm-$2)) $$(aflags-$2)) +else +$$(error "Don't know what to do with $1") +endif + + +comp-flags-$2 += -Wp,-MD,$$(comp-temp-dep-$2) \ + $$(filter-out $$(CPPFLAGS_REMOVE) $$(cppflags-remove) \ + $$(cppflags-remove-$2), \ + $$(nostdinc) $$(CPPFLAGS) \ + $$(addprefix -I,$$(incdirs$$(comp-sm-$2))) \ + $$(cppflags$$(comp-sm-$2)) $$(cppflags-$2)) + +comp-cmd-$2 = $$(CC) $$(comp-flags-$2) -c $$< -o $$@ + +-include $$(comp-cmd-file-$2) +-include $$(comp-dep-$2) + + +$2: $1 FORCE +# Check if any prerequisites are newer than the target and +# check if command line has changed + $$(if $$(strip $$? $$(filter-out $$(comp-cmd-$2), $$(old-cmd-$2)) \ + $$(filter-out $$(old-cmd-$2), $$(comp-cmd-$2))), \ + @set -e ;\ + mkdir -p $$(dir $2) ;\ + echo [$$(comp-sm-$2)] CC $1 ;\ + $(cmd-echo) $$(subst \",\\\",$$(comp-cmd-$2)) ;\ + $$(comp-cmd-$2) ;\ + $(cmd-fixdep) $$(dir $2) < $$(comp-temp-dep-$2) > \ + $$(comp-dep-$2) ;\ + rm -f $$(comp-temp-dep-$2) ;\ + echo "old-cmd-$2 := $$(subst \",\\\",$$(comp-cmd-$2))" > \ + $$(comp-cmd-file-$2) ;\ + ) + +endef + +$(foreach f, $(srcs), $(eval $(call \ + process_srcs,$(f),$(out-dir)$(base-prefix)$$(basename $f).o))) diff --git a/mk/config.mk b/mk/config.mk new file mode 100644 index 00000000000..6d2d3630ea6 --- /dev/null +++ b/mk/config.mk @@ -0,0 +1,39 @@ +# WARNS from undefined, 1, 2 and 3. 3 means we have the most warning messages +WARNS ?= 3 + +# Define NOWERROR=1 so that warnings are not treated as errors +# NOWERROR=1 + +# Define DEBUG=1 to compile with -g option +# DEBUG=1 + +# Define TEE_ACCEPT_UNSIGNED_BINARIES=1 so that non-signed TA are loaded +# It should not be defined in a real product +TEE_ACCEPT_UNSIGNED_BINARIES=1 + +# CFG_TEE_FW_DEBUG +# If 1, debug mode of the tee firmware (CPU restart, Core Status) +CFG_TEE_FW_DEBUG?=0 + +# CFG_TEE_CORE_LOG_LEVEL +# Max level of the tee core traces. 0 means disable, 5 is max. +# Supported values: 0 (no traces) to 5 (all traces) +# If CFG_TEE_DRV_DEBUGFS is set, the level of traces to print can be +# dynamically changes via debugfs in the range 1 => CFG_TEE_CORE_LOG_LEVEL +CFG_TEE_CORE_LOG_LEVEL?=2 + +# CFG_TEE_TA_LOG_LEVEL +# TA and TEECore log level +# Supported values: 0 (no traces) to 5 (all traces) +# If CFG_TEE_DRV_DEBUGFS is set, the level of traces to print can be +# dynamically changes via debugfs in the range 1 => CFG_TEE_TA_LOG_LEVEL +CFG_TEE_TA_LOG_LEVEL?=2 + + +# If 1, enable debug features of the user mem module. This module track memory +# allocation of the user ta. +# Debug features include check of buffer overflow, statistics, +# marck/check heap feature +# Enabling this could decrease efficiency +CFG_TEE_CORE_USER_MEM_DEBUG?=1 + diff --git a/mk/gcc.mk b/mk/gcc.mk new file mode 100644 index 00000000000..f6fccf42652 --- /dev/null +++ b/mk/gcc.mk @@ -0,0 +1,17 @@ + +CC = $(CROSS_COMPILE)gcc +LD = $(CROSS_COMPILE)ld +AR = $(CROSS_COMPILE)ar +NM = $(CROSS_COMPILE)nm +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf + +nostdinc := -nostdinc -isystem $(shell $(CC) -print-file-name=include \ + 2> /dev/null) + +# Get location of libgcc from gcc +libgcc := $(shell $(CC) $(comp-cflags$(sm)) -print-libgcc-file-name \ + 2> /dev/null) + + diff --git a/mk/lib.mk b/mk/lib.mk new file mode 100644 index 00000000000..965618f5725 --- /dev/null +++ b/mk/lib.mk @@ -0,0 +1,30 @@ +# Input +# +# libname tells the name of the lib and +# libdir tells directory of lib which also is used as input to +# mk/subdir.mk +# +# Output +# +# updated cleanfiles and +# updated libfiles, libdirs, libnames and libdeps + + +subdirs = $(libdir) +include mk/subdir.mk +include mk/compile.mk + +lib-libfile = $(out-dir)$(base-prefix)$(libdir)/lib$(libname).a +cleanfiles := $(cleanfiles) $(lib-libfile) +libfiles := $(lib-libfile) $(libfiles) +libdirs := $(out-dir)$(base-prefix)$(libdir) $(libdirs) +libnames := $(libname) $(libnames) +libdeps := $(lib-libfile) $(libdeps) + +$(lib-libfile): $(objs) + @echo AR $@ + @mkdir -p $(dir $@) + $(q)$(AR) rcs $@ $^ + +# Clean residues from processing +objs := diff --git a/mk/subdir.mk b/mk/subdir.mk new file mode 100644 index 00000000000..38723522658 --- /dev/null +++ b/mk/subdir.mk @@ -0,0 +1,68 @@ +# Input +# +# subdirs tells the subdirectories to descend +# +# Output +# +# set srcs +# set cflags-$(oname) cflags-remove-$(oname) +# aflags-$(oname) aflags-remove-$(oname) +# cppflags-$(oname) cppflags-remove-$(oname) +# for each file found, oname is the name of the object file for corresponding +# source file + +srcs := + +define process-subdir-srcs-y +ifeq ($$(sub-dir),.) +fname := $1 +oname := $(out-dir)$(base-prefix)$(basename $1).o +else +fname := $(sub-dir)/$1 +oname := $(out-dir)$(base-prefix)$(basename $$(sub-dir)/$1).o +endif +srcs += $$(fname) +cflags-$$(oname) := $$(cflags-y) $$(cflags-$(1)-y) +cflags-remove-$$(oname) := $$(cflags-remove-y) \ + $$(cflags-remove-$(1)-y) +cppflags-$$(oname) := $$(cppflags-y) $$(cppflags-$(1)-y) +cppflags-remove-$$(oname) := $$(cppflags-remove-y) \ + $$(cppflags-remove-$(1)-y) +aflags-$$(oname) := $$(aflags-y) $$(aflags-$(1)-y) +aflags-remove-$$(oname) := $$(aflags-remove-y) \ + $$(aflags-remove-$(1)-y) +# Clear local filename specific variables to avoid accidental reuse +# in another subdirectory +cflags-$(1)-y := +cflags-remove-$(1)-y := +cppflags-$(1)-y := +cppflags-remove-$(1)-y := +aflags-$(1)-y := +aflags-remove-$(1)-y := +fname := +oname := +endef #process-subdir-srcs-y + +define process-subdir +sub-dir := $1 +include $1/sub.mk +sub-subdirs := $$(addprefix $1/,$$(subdirs-y)) +incdirs$(sm) := $(incdirs$(sm)) $$(addprefix $1/,$$(global-incdirs-y)) + +# Process files in current directory +$$(foreach s, $$(srcs-y), $$(eval $$(call process-subdir-srcs-y,$$(s)))) +# Clear flags used when processing current directory +srcs-y := +cflags-y := +cppflags-y := +aflags-y := +cflags-remove-y := +subdirs-y := +global-incdirs-y := + +# Process subdirectories in current directory +$$(foreach sd, $$(sub-subdirs), $$(eval $$(call process-subdir,$$(sd)))) +endef #process-subdir + +# Top subdirectories +$(foreach sd, $(subdirs), $(eval $(call process-subdir,$(sd)))) diff --git a/scripts/fixdep b/scripts/fixdep new file mode 100755 index 00000000000..b7c31d28bbb --- /dev/null +++ b/scripts/fixdep @@ -0,0 +1,19 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +if ($#ARGV != 0) { + die "Usage: fixdep "; +} + +my $first_line = 1; + +while () { + if ($first_line) { + print "$ARGV[0]$_"; + $first_line = 0; + } else { + print "$_"; + } +} diff --git a/ta/arch/arm32/link.mk b/ta/arch/arm32/link.mk new file mode 100644 index 00000000000..12d5394a078 --- /dev/null +++ b/ta/arch/arm32/link.mk @@ -0,0 +1,43 @@ +link-out-dir = $(out-dir) + +link-script = $(TA_DEV_KIT_DIR)/src/user_ta_elf_arm.lds +link-script-pp = $(link-out-dir)ta.lds + +AWK = awk + +all: $(link-out-dir)$(binary).elf $(link-out-dir)$(binary).dmp \ + $(link-out-dir)$(binary).bin +cleanfiles += $(link-out-dir)$(binary).elf $(link-out-dir)$(binary).dmp +cleanfiles += $(link-out-dir)$(binary).map +cleanfiles += $(link-out-dir)$(binary).bin +cleanfiles += $(link-script-pp) + +link-ldflags = $(LDFLAGS) +link-ldflags += -T $(link-script-pp) -Map=$(link-out-dir)$(binary).map +link-ldflags += --sort-section=alignment + +# Macro to reverse a list +reverse = $(if $(wordlist 2,2,$(1)),$(call reverse,$(wordlist 2,$(words $(1)),$(1))) $(firstword $(1)),$(1)) + +link-ldadd = $(LDADD) +link-ldadd += $(addprefix -L,$(libdirs)) +link-ldadd += $(addprefix -l,$(call reverse,$(libnames))) +ldargs-$(binary).elf := $(link-ldflags) $(objs) $(link-ldadd) $(libgcc) + + +$(link-script-pp): $(link-script) $(MAKEFILE_LIST) + @echo PP $< + $(q)cat < $< > $@ + + +$(link-out-dir)$(binary).elf: $(objs) $(libdeps) $(link-script-pp) + @echo LD $@ + $(q)$(LD) $(ldargs-$(binary).elf) -o $@ + +$(link-out-dir)$(binary).dmp: $(link-out-dir)$(binary).elf + @echo OBJDUMP $@ + $(q)$(OBJDUMP) -l -x -d $< > $@ + +$(link-out-dir)$(binary).bin: $(link-out-dir)$(binary).elf + @echo OBJCOPY $@ + $(q)$(OBJCOPY) -O binary $< $@ diff --git a/ta/arch/arm32/user_ta_elf_arm.lds b/ta/arch/arm32/user_ta_elf_arm.lds new file mode 100644 index 00000000000..197ce2d6921 --- /dev/null +++ b/ta/arch/arm32/user_ta_elf_arm.lds @@ -0,0 +1,153 @@ +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) + +/* The format of the TA binary should be + * + * ta_head + * ta_func_head + * RO Sections + * RW Sections + * ZI Sections + */ + +SECTIONS +{ + .ta_head : {*(.ta_head)} + .ta_func_head : {*(.ta_func_head)} + + /* RO sections */ + + start_of_RO_sections = .; + + /*. = 0x00100000 */ /* uTA runs in vmem at 1st MiB */ + .text : + { + *(.text .text.*) + *(.stub) + + /* ARM glue code for ARM and thumb */ + *(.glue_7) + *(.glue_7t) + + /* + * The below input sections should not be of use, but put + * in this output section to define their position. + */ + + /* Workaround for an erratum in ARM's VFP11 coprocessor */ + *(.vfp11_veneer) + /* ARMv4 interworking compatibility */ + *(.v4_bx) + /* GCC/ld specific */ + *(.gnu.linkonce.t.*) + *(.gnu.linkonce.r.*) + *(.gnu.warning) + *(.gcc_except_table) + } + .rodata : + { + *(.rodata .rodata.*) + *(.rodata1) + . = ALIGN(4); + } + .rel.dyn : + { + start_of_rel_data_section = .; + *(.rel.data) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + end_of_rel_data_section = .; + start_of_rela_data_section = .; + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + end_of_rela_data_section = .; + } + + . = ALIGN(4); + end_of_RO_sections = .; + + /* RW sections */ + + start_of_RW_sections = .; + start_of_GOT_sections = .; + + .data : + { + *(.got.*) + *(.got) + end_of_GOT_sections = .; + + *(.ta_heap_base) + + *(.data .data.*) + /* GCC/ld specific */ + *(.gnu.linkonce.d.*) + } + .data1 : {*(.data1)} + .tdata : {*(.tdata .tdata.*)} + + end_of_RW_sections = .; + + /* ZI sections */ + + start_of_ZI_sections = .; + + .bss : + { + *(.dynbss) + *(.bss .bss.*) + /* GCC/ld specific */ + *(.gnu.linkonce.b.*) + } + .tbss : {*(.tbss .tbss.*)} + + end_of_ZI_sections = .; + + .interp ALIGN(4) : { *(.interp) } + .hash ALIGN(4) : { *(.hash) } + .dynsym ALIGN(4) : { *(.dynsym) } + .dynstr ALIGN(4) : { *(.dynstr) } + .gnu.version ALIGN(4) : { *(.gnu.version) } + .gnu.version_d ALIGN(4) : { *(.gnu.version_d) } + .gnu.version_r ALIGN(4) : { *(.gnu.version_r) } + .dynamic ALIGN(4) : { *(.dynamic) } + + /* Stabs debugging sections. */ + .stab : { *(.stab) } + .stabstr : { *(.stabstr) } + .stab.excl : { *(.stab.excl) } + .stab.exclstr : { *(.stab.exclstr) } + .stab.index : { *(.stab.index) } + .stab.indexstr : { *(.stab.indexstr) } + .comment : { *(.comment) } + + /* + * Remove relocation information for GOT and the headers. + * All needed relocation informtion should already be matched above. + */ + .junkedrel /*ALIGN(4)*/ : + { + *(.rel.*) + *(.rela.*) + } + + PROVIDE(linker_RO_sections_size = end_of_RO_sections - start_of_RO_sections); + + linker_RW_sections_size = end_of_RW_sections - start_of_RW_sections; + + ZI_sections_size = end_of_ZI_sections - start_of_ZI_sections; + ASSERT(ZI_sections_size <= 0xfffff, "Too large ZI_sections_size") + /* + * Reserve the last two struct user_ta_func_head elements for the + * properties + */ + linker_res_funcs_ZI_sections_size = (2 << 20) + ZI_sections_size; + + GOT_sections_size = end_of_GOT_sections - start_of_GOT_sections; + rel_sections_size = end_of_rel_data_section - start_of_rel_data_section; + rela_sections_size = end_of_rela_data_section - start_of_rela_data_section; + ASSERT(rela_sections_size == 0, "Can't handle nonzero rela_sections_size") + ASSERT(GOT_sections_size <= 0xffff, "Too large GOT_sections_size") + ASSERT(rel_sections_size <= 0xffff, "Too large rel_sections_size") + linker_rel_dyn_GOT = (rel_sections_size << 16) + GOT_sections_size; + +} + diff --git a/ta/arch/arm32/user_ta_header.c b/ta/arch/arm32/user_ta_header.c new file mode 100644 index 00000000000..289eac9c673 --- /dev/null +++ b/ta/arch/arm32/user_ta_header.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include + +#ifndef TA_TRACE_LEVEL_DEFAULT +#define TA_TRACE_LEVEL_DEFAULT CFG_TEE_TA_LOG_LEVEL +#endif + +/* exprted to user_ta_header.c, built within TA */ +void ta_entry_close_session(uint32_t session_id) + /*__attribute__((noreturn))*/ ; + +void ta_entry_open_session(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS], + uint32_t session_id) + /*__attribute__((noreturn))*/ ; + +void ta_entry_invoke_command(uint32_t cmd_id, uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS], + uint32_t session_id) + /*__attribute__((noreturn))*/ ; + +/* These externs are defined in the ld link script */ +extern uint32_t linker_RO_sections_size; +extern uint32_t linker_RW_sections_size; +extern uint32_t linker_res_funcs_ZI_sections_size; +extern uint32_t linker_rel_dyn_GOT; + +/* Note that cmd_id is not used in a User Mode TA */ +const struct user_ta_func_head user_ta_func_head[] + __attribute__ ((section(".ta_func_head"))) = +{ + { + 0, (uint32_t) ta_entry_open_session}, { + 0, (uint32_t) ta_entry_close_session}, { + 0, (uint32_t) ta_entry_invoke_command}, { + TA_FLAGS, 0 /* Spare */ }, + { +TA_DATA_SIZE, TA_STACK_SIZE},}; + +const struct user_ta_head ta_head __attribute__ ((section(".ta_head"))) = { + /* UUID, unique to each TA */ + TA_UUID, + /* Number of functions in the TA */ + sizeof(user_ta_func_head) / sizeof(struct user_ta_func_head), + /* Section size information */ + (uint32_t) & linker_RO_sections_size, + (uint32_t) & linker_RW_sections_size, + (uint32_t) & linker_res_funcs_ZI_sections_size, + (uint32_t) & linker_rel_dyn_GOT, + /* Hash type, filled in by sign-tool */ + 0, + /* TA trace level */ + /* TA_TRACE_LEVEL_DEFAULT, */ +}; + +/* Filled in by TEE Core when loading the TA */ +uint8_t *ta_heap_base __attribute__ ((section(".ta_heap_base"))); + +const size_t ta_data_size = TA_DATA_SIZE; + +const struct user_ta_property ta_props[] = { + {"gpd.ta.singleInstance", USER_TA_PROP_TYPE_BOOL, + &(const bool){(TA_FLAGS & TA_FLAG_SINGLE_INSTANCE) != 0}}, + + {"gpd.ta.multiSession", USER_TA_PROP_TYPE_BOOL, + &(const bool){(TA_FLAGS & TA_FLAG_MULTI_SESSION) != 0}}, + + {"gpd.ta.instanceKeepAlive", USER_TA_PROP_TYPE_BOOL, + &(const bool){(TA_FLAGS & TA_FLAG_INSTANCE_KEEP_ALIVE) != 0}}, + + {"gpd.ta.dataSize", USER_TA_PROP_TYPE_U32, + &(const uint32_t){TA_DATA_SIZE}}, + + {"gpd.ta.stackSize", USER_TA_PROP_TYPE_U32, + &(const uint32_t){TA_STACK_SIZE}}, +/* + * Extended propietary properties, name of properties must not begin with + * "gpd." + */ +#ifdef TA_CURRENT_TA_EXT_PROPERTIES + TA_CURRENT_TA_EXT_PROPERTIES +#endif +}; + +const size_t ta_num_props = sizeof(ta_props) / sizeof(ta_props[0]); + +int tahead_get_trace_level(void) +{ + /* + * Store trace level in TA head structure, as ta_head.prop_tracelevel + */ + return TA_TRACE_LEVEL_DEFAULT; +} diff --git a/ta/mk/ta_dev_kit.mk b/ta/mk/ta_dev_kit.mk new file mode 100644 index 00000000000..6170d56b3bc --- /dev/null +++ b/ta/mk/ta_dev_kit.mk @@ -0,0 +1,58 @@ + + +# Get the dir of the ta-dev-kit, requires make version 3.81 or later +ta-dev-kit-dir := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))..) + + +.PHONY: all +all: + +sm := ta +sm-$(ta) := y +binary := $(BINARY) + +cmd-fixdep := $(ta-dev-kit-dir)/scripts/fixdep + +ifneq ($O,) +out-dir := $O/ +endif + +ifneq ($V,1) +q := @ +cmd-echo := true +else +q := +cmd-echo := echo +endif + +cflags$(sm) += -fno-short-enums +cppflags$(sm) += -I. -I$(ta-dev-kit-dir)/include + +ifeq ($(DEBUG),1) +cflags$(sm) += -O0 +else +cflags$(sm) += -Os +endif +cflags$(sm) += -g -g3 +aflags$(sm) += -g -g3 + + +libdirs += $(ta-dev-kit-dir)/lib +libnames += c mpa utee +libdeps += $(ta-dev-kit-dir)/lib/libutils.a +libdeps += $(ta-dev-kit-dir)/lib/libmpa.a +libdeps += $(ta-dev-kit-dir)/lib/libutee.a + +.PHONY: clean +clean: + @echo Cleaning + ${q}rm -f $(cleanfiles) + + +subdirs = . +include $(ta-dev-kit-dir)/mk/subdir.mk +vpath %.c $(ta-dev-kit-dir)/src +srcs += user_ta_header.c + +include $(ta-dev-kit-dir)/mk/compile.mk +include $(ta-dev-kit-dir)/mk/link.mk diff --git a/ta/ta.mk b/ta/ta.mk new file mode 100644 index 00000000000..d2aa29480dd --- /dev/null +++ b/ta/ta.mk @@ -0,0 +1,79 @@ +include mk/cleanvars.mk + +# Set current submodule (used for module specific flags compile result etc) +sm := user_ta +sm-$(sm) := y + +cppflags$(sm) += $(platform-cppflags) $(user_ta-platform-cppflags) +cflags$(sm) += $(platform-cflags) $(user_ta-platform-cflags) +aflags$(sm) += $(platform-aflags) $(user_ta-platform-aflags) + +# Config flags from mk/config.mk +cppflags$(sm) += -DCFG_TEE_TA_LOG_LEVEL=$(CFG_TEE_TA_LOG_LEVEL) +cppflags$(sm) += -DCFG_TEE_CORE_USER_MEM_DEBUG=$(CFG_TEE_CORE_USER_MEM_DEBUG) + + +base-prefix := $(sm)- + +libname = utils +libdir = lib/libutils +include mk/lib.mk + +libname = mpa +libdir = lib/libmpa +include mk/lib.mk + +libname = utee +libdir = lib/libutee +include mk/lib.mk + +base-prefix := + +incdirs-host := $(filter-out lib/libutils%, $(incdirs$(sm))) + +# +# Copy lib files and exported headers from each lib +# + +define copy-file +$2/$$(notdir $1): $1 + @mkdir -p $$(dir $$@) + cp $$< $$@ + +cleanfiles += $2/$$(notdir $1) +all: $2/$$(notdir $1) +endef + +# Copy the .a files +$(foreach f, $(libfiles), \ + $(eval $(call copy-file, $(f), $(out-dir)export-user_ta/lib))) + +# Copy .mk files +ta-mkfiles = mk/compile.mk mk/subdir.mk $(wildcard ta/arch/$(ARCH)/link.mk) \ + ta/mk/ta_dev_kit.mk +$(foreach f, $(ta-mkfiles), \ + $(eval $(call copy-file, $(f), $(out-dir)export-user_ta/mk))) + +# Copy the .h files for TAs +define copy-incdir +sf := $(subst $1/, , $(shell find $1 -name "*.h")) +$$(foreach h, $$(sf), $$(eval $$(call copy-file, $1/$$(h), \ + $$(subst /./,/,$2/$$(dir $$(h)))))) +endef +$(foreach d, $(incdirs$(sm)), \ + $(eval $(call copy-incdir, $(d), $(out-dir)export-user_ta/include))) + +# Copy the .h files needed by host +$(foreach d, $(incdirs-host), \ + $(eval $(call copy-incdir, $(d), $(out-dir)export-user_ta/host_include))) + +# Copy the src files +ta-srcfiles = ta/arch/$(ARCH)/user_ta_header.c \ + $(wildcard ta/arch/$(ARCH)/user_ta_elf_arm.lds) +$(foreach f, $(ta-srcfiles), \ + $(eval $(call copy-file, $(f), $(out-dir)export-user_ta/src))) + +# Copy the scripts +ta-scripts = scripts/fixdep +$(foreach f, $(ta-scripts), \ + $(eval $(call copy-file, $(f), $(out-dir)export-user_ta/scripts)))